os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/ram_fat_table32.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 
   368 /**
   369     Allocate and link a cluster chain, leaves if there are not enough free clusters.
   370     Chain starts as close as possible to aNearestCluster, last cluster will be marked as EOF.
   371 
   372     @param aNumber Number of clusters to allocate
   373     @param aNearestCluster Cluster the new chain should be nearest to
   374     @leave System wide error codes
   375     @return The first cluster number allocated
   376 */
   377 TUint32 CRamFatTable::AllocateClusterListL(TUint32 aNumber, TUint32 aNearestCluster)
   378 	{
   379     __PRINT2(_L("CRamFatTable::AllocateClusterList() N:%d,NearestCL:%d"),aNumber,aNearestCluster);
   380 	__ASSERT_DEBUG(aNumber>0, Fault(EFatBadParameter));
   381 
   382 	if(!RequestFreeClusters(aNumber))
   383     	{
   384 		__PRINT(_L("CRamFatTable::AllocateClusterListL - leaving KErrDirFull"));
   385 		User::Leave(KErrDiskFull);
   386 		}
   387 
   388 	//-- if this leaves for some reason, there will be no lost clusters
   389     TInt firstCluster = aNearestCluster = AllocateSingleClusterL(aNearestCluster);
   390 	
   391     
   392     if (aNumber>1)
   393 	    {//-- if this part leaves (e.g. fail to expand the RAM drive), we will need to handle the first allocated EOC
   394     	TRAPD(nRes, ExtendClusterListL(aNumber-1, (TInt&)aNearestCluster));
   395         if(nRes != KErrNone)
   396             {
   397             __PRINT1(_L("CRamFatTable::AllocateClusterListL:ExtendClusterListL() failed with %d") ,nRes);
   398             FreeClusterListL(firstCluster); //-- clean up EOC in firstCluster
   399             User::Leave(nRes);
   400             }
   401         }
   402 
   403 
   404     return firstCluster;
   405 	}	
   406 
   407 /**
   408 Allocate and mark as EOF a single cluster as close as possible to aNearestCluster,
   409 calls base class implementation but must Enlarge the RAM drive first. Allocated cluster RAM area will be zero-filled.
   410 
   411 @param aNearestCluster Cluster the new cluster should be nearest to
   412 @leave System wide error codes
   413 @return The cluster number allocated
   414 */
   415 TUint32 CRamFatTable::AllocateSingleClusterL(TUint32 aNearestCluster)
   416     {
   417     __PRINT(_L("CRamFatTable::AllocateSingleClusterL"));
   418     iOwner->EnlargeL(1<<iOwner->ClusterSizeLog2()); //  First enlarge the RAM drive
   419     TInt fileAllocated=CFatTable::AllocateSingleClusterL(aNearestCluster); //   Now update the free cluster and fat/fit
   420     ZeroFillCluster(fileAllocated);  //-- zero-fill allocated cluster 
   421     return(fileAllocated);
   422     }   
   423 
   424 
   425 /**
   426     Extend a file or directory cluster chain, enlarging RAM drive first. Allocated clusters are zero-filled.
   427     Leaves if there are no free clusters (the disk is full).
   428     Note that method now doesn't call CFatTable::ExtendClusterListL() from its base class, be careful making changes there.
   429 
   430     @param aNumber      number of clusters to allocate
   431     @param aCluster     starting cluster number / ending cluster number after
   432     @leave KErrDiskFull + system wide error codes
   433 */
   434 void CRamFatTable::ExtendClusterListL(TUint32 aNumber, TInt& aCluster)
   435     {
   436     __PRINT2(_L("CRamFatTable::ExtendClusterListL(%d, %d)"), aNumber, aCluster);
   437     __ASSERT_DEBUG(aNumber>0,Fault(EFatBadParameter));
   438 
   439     iOwner->EnlargeL(aNumber<<iOwner->ClusterSizeLog2());
   440 
   441     while(aNumber && GetNextClusterL(aCluster))
   442         aNumber--;
   443 
   444     if(!aNumber)
   445         return;
   446 
   447     if (NumberOfFreeClusters() < aNumber)
   448         {
   449         __PRINT(_L("CRamFatTable::ExtendClusterListL - leaving KErrDirFull"));
   450         User::Leave(KErrDiskFull);
   451         }
   452 
   453     while(aNumber--)
   454         {
   455         const TInt freeCluster=FindClosestFreeClusterL(aCluster);
   456 
   457         WriteFatEntryEofL(freeCluster); //  Must write EOF for FindClosestFreeCluster to work again
   458         DecrementFreeClusterCount(1);
   459         WriteL(aCluster,freeCluster);
   460         aCluster=freeCluster;
   461         ZeroFillCluster(freeCluster); //-- zero fill just allocated cluster (RAM area)
   462         }
   463 
   464     SetFreeClusterHint(aCluster); 
   465   
   466     }
   467 
   468 /**
   469 Mark a chain of clusters as free in the FAT. Shrinks the RAM drive once the
   470 clusters are free 
   471 
   472 @param aCluster Start cluster of cluster chain to free
   473 @leave System wide error codes
   474 */
   475 void CRamFatTable::FreeClusterListL(TUint32 aCluster)
   476     {
   477     __PRINT1(_L("CRamFatTable::FreeClusterListL aCluster=%d"),aCluster);
   478     if (aCluster==0)
   479         return; // File has no cluster allocated
   480 
   481     const TInt clusterShift=iOwner->ClusterSizeLog2();
   482     TInt startCluster=aCluster;
   483     TInt endCluster=0;
   484     TInt totalFreed=0;
   485     TLinAddr srcEnd=0;
   486 
   487     if(IsFat32())
   488         {
   489         while(endCluster!=EOF_32Bit)
   490             {
   491             TInt num=CountContiguousClustersL(startCluster,endCluster,KMaxTInt);
   492             if (GetNextClusterL(endCluster)==EFalse || endCluster==0)
   493                 endCluster=EOF_32Bit;   // endCluster==0 -> file contained FAT loop
   494 
   495         //  Real position in bytes of the start cluster in the data area
   496             TLinAddr startClusterPos=I64LOW(DataPositionInBytes(startCluster));
   497         //  Sliding value when more than one block is freed
   498             TLinAddr trg=startClusterPos-(totalFreed<<clusterShift);
   499             __PRINT1(_L("trg=0x%x"),trg);
   500 
   501         //  Beginning of data area to move
   502             TLinAddr srcStart=startClusterPos+(num<<clusterShift);
   503             __PRINT1(_L("srcStart=0x%x"),srcStart);
   504         //  Position of next part of cluster chain or position of end of ram drive
   505             if (endCluster==EOF_32Bit)  //  Last cluster is the end of the chain
   506                 {
   507             
   508         
   509             //  Fixed to use the genuine RAM drive size rather than the number
   510             //  of free clusters - though they *should* be the same
   511             //  It avoids the problem of iFreeClusters getting out of sync with 
   512             //  the RAM drive size but doesn't solve the issue of why it can happen...
   513                 
   514                 srcEnd=I64LOW(iOwner->Size());
   515                 __PRINT1(_L("srcEnd=0x%x"),srcEnd);
   516                 }
   517             else                        //  Just move up to the next part of the chain
   518                 srcEnd=I64LOW(DataPositionInBytes(endCluster));
   519 
   520         //-- Copy (srcEnd-srcStart) bytes from iRamDiskBase+srcStart onto iRamDiskBase+trg
   521         //-- zero-filling free space to avoid leaving something important there
   522         ASSERT(srcEnd >= srcStart);
   523         if(srcEnd-srcStart > 0)
   524             { 
   525             MemCopyFillZ(iRamDiskBase+trg,iRamDiskBase+srcStart,srcEnd-srcStart);
   526             }
   527         else
   528             {//-- we are freeing the cluster chain at the end of the RAM drive; Nothing to copy to the drive space that has become free,
   529              //-- but nevertheless zero fill this space.
   530             Mem::FillZ(iRamDiskBase+trg, num<<clusterShift);
   531             }
   532 
   533 
   534             totalFreed+=num;
   535             startCluster=endCluster;
   536             UpdateIndirectionTable(srcStart>>clusterShift,srcEnd>>clusterShift,totalFreed);
   537             }
   538         }
   539     else
   540         {
   541         while(endCluster!=EOF_16Bit)
   542             {
   543             TInt num=CountContiguousClustersL(startCluster,endCluster,KMaxTInt);
   544             if (GetNextClusterL(endCluster)==EFalse || endCluster==0)
   545                 endCluster=EOF_16Bit;   // endCluster==0 -> file contained FAT loop
   546 
   547         //  Real position in bytes of the start cluster in the data area
   548             TLinAddr startClusterPos=I64LOW(DataPositionInBytes(startCluster));
   549         //  Sliding value when more than one block is freed
   550             TLinAddr trg=startClusterPos-(totalFreed<<clusterShift);
   551             __PRINT1(_L("trg=0x%x"),trg);
   552 
   553         //  Beginning of data area to move
   554             TLinAddr srcStart=startClusterPos+(num<<clusterShift);
   555             __PRINT1(_L("srcStart=0x%x"),srcStart);
   556         //  Position of next part of cluster chain or position of end of ram drive
   557             if (endCluster==EOF_16Bit)  //  Last cluster is the end of the chain
   558                 {
   559             
   560         
   561             //  Fixed to use the genuine RAM drive size rather than the number
   562             //  of free clusters - though they *should* be the same
   563             //  It avoids the problem of iFreeClusters getting out of sync with 
   564             //  the RAM drive size but doesn't solve the issue of why it can happen...
   565                 
   566                 srcEnd=I64LOW(iOwner->Size());
   567                 __PRINT1(_L("srcEnd=0x%x"),srcEnd);
   568                 }
   569             else                        //  Just move up to the next part of the chain
   570                 srcEnd=I64LOW(DataPositionInBytes(endCluster));
   571 
   572         //-- Copy (srcEnd-srcStart) bytes from iRamDiskBase+srcStart onto iRamDiskBase+trg
   573         //-- zero-filling free space to avoid leaving something important there
   574         ASSERT(srcEnd >= srcStart);
   575         if(srcEnd-srcStart > 0)
   576             { 
   577             MemCopyFillZ(iRamDiskBase+trg,iRamDiskBase+srcStart,srcEnd-srcStart);
   578             }    
   579         else
   580             {//-- we are freeing the cluster chain at the end of the RAMdrive; Nothing to copy to the drive space that has become free,
   581              //-- but nevertheless zero fill this space.
   582             Mem::FillZ(iRamDiskBase+trg, num<<clusterShift);
   583             }    
   584         
   585             totalFreed+=num;
   586             startCluster=endCluster;
   587             UpdateIndirectionTable(srcStart>>clusterShift,srcEnd>>clusterShift,totalFreed);
   588             }
   589         }
   590     TInt bytesFreed=totalFreed<<clusterShift;
   591     
   592 //  First free the cluster list
   593     CFatTable::FreeClusterListL(aCluster);
   594 //  Now reduce the size of the RAM drive
   595     iOwner->ReduceSizeL(srcEnd-bytesFreed,bytesFreed);
   596     }
   597 
   598 /**
   599 Shift any clusters between aStart and anEnd backwards by aClusterShift
   600 
   601 @param aStart Start of shift region
   602 @param anEnd End of shift region
   603 @param aClusterShift amount to shift cluster by
   604 */
   605 void CRamFatTable::UpdateIndirectionTable(TUint32 aStart,TUint32 anEnd,TInt aClusterShift)
   606     {
   607     __PRINT(_L("CRamFatTable::UpdateIndirectionTable"));
   608 #if defined(__WINS__)
   609     TUint32 count=iOwner->MaxClusterNumber();
   610     while (count--)
   611         {
   612         TUint32 cluster=count;
   613         ReadIndirectionTable(cluster);
   614         if (cluster>=aStart && cluster<anEnd)
   615             WriteIndirectionTable(count,cluster-aClusterShift);
   616         }
   617 #else
   618     TUint16* table=(TUint16*)(RamDiskBase()+iIndirectionTablePos);
   619     TUint16* entry=table+iOwner->MaxClusterNumber();
   620     while (entry>table)
   621         {
   622         TUint32 cluster=*--entry;
   623         if (cluster<aStart)
   624             continue;
   625         if (cluster<anEnd)
   626             *entry=TUint16(cluster-aClusterShift);
   627         }
   628 #endif
   629     }
   630 
   631 
   632