1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/ram_fat_table32.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,632 @@
1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32\sfat32\ram_fat_table32.cpp
1.18 +// FAT16/32 File Allocation Table classes implementation for the RAM media
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 + @file
1.24 + @internalTechnology
1.25 +*/
1.26 +
1.27 +
1.28 +
1.29 +#include "sl_std.h"
1.30 +#include "sl_fatcache32.h"
1.31 +#include "fat_table32.h"
1.32 +
1.33 +
1.34 +//---------------------------------------------------------------------------------------------------------------------------------------
1.35 +
1.36 +//#######################################################################################################################################
1.37 +//# CRamFatTable class implementation
1.38 +//#######################################################################################################################################
1.39 +
1.40 +/**
1.41 + Constructor, the RamFatTable allows disk compression by redirecting the FAT
1.42 +
1.43 + @param aOwner Owning mount.
1.44 +*/
1.45 +CRamFatTable::CRamFatTable(CFatMountCB& aOwner)
1.46 + :CFatTable(aOwner)
1.47 +{
1.48 + iFatTablePos=aOwner.FirstFatSector()<<aOwner.SectorSizeLog2();
1.49 + iIndirectionTablePos=iFatTablePos+aOwner.FatSizeInBytes();
1.50 +}
1.51 +
1.52 +/** factory method */
1.53 +CRamFatTable* CRamFatTable::NewL(CFatMountCB& aOwner)
1.54 +{
1.55 + __PRINT1(_L("CRamFatTable::NewL() drv:%d"),aOwner.DriveNumber());
1.56 +
1.57 + CRamFatTable* pSelf = new (ELeave) CRamFatTable(aOwner);
1.58 +
1.59 + CleanupStack::PushL(pSelf);
1.60 + pSelf->InitializeL();
1.61 + CleanupStack::Pop();
1.62 +
1.63 + return pSelf;
1.64 +}
1.65 +
1.66 +
1.67 +void CRamFatTable::InitializeL()
1.68 +{
1.69 + CFatTable::InitializeL();
1.70 +
1.71 + ASSERT(iMediaAtt & KMediaAttVariableSize);
1.72 + ASSERT(FatType() == EFat16 || FatType()== EFat32);
1.73 +
1.74 + iFatTablePos=iOwner->FirstFatSector()<<iOwner->SectorSizeLog2();
1.75 + iIndirectionTablePos=iFatTablePos+iOwner->FatSizeInBytes();
1.76 +
1.77 + //-- set RAM disk base
1.78 + TLocalDriveCapsV2 caps;
1.79 + TPckg<TLocalDriveCapsV2> capsPckg(caps);
1.80 + User::LeaveIfError(iOwner->LocalDrive()->Caps(capsPckg));
1.81 +
1.82 + iRamDiskBase = caps.iBaseAddress;
1.83 +}
1.84 +
1.85 +/**
1.86 + Just Count free clusters in the FAT
1.87 +*/
1.88 +void CRamFatTable::MountL(const TMountParams& /*aMountParam*/)
1.89 +{
1.90 + CountFreeClustersL();
1.91 +}
1.92 +
1.93 +
1.94 +/**
1.95 + Return the start address of the Ram Drive
1.96 + @return start address of the Ram Drive
1.97 +*/
1.98 +TUint8 *CRamFatTable::RamDiskBase() const
1.99 + {
1.100 + return(iRamDiskBase);
1.101 + }
1.102 +
1.103 +
1.104 +/**
1.105 + Allocate a new cluster number
1.106 +
1.107 + @return New cluster number
1.108 +*/
1.109 +TInt CRamFatTable::AllocateClusterNumber()
1.110 + {
1.111 + return(iOwner->MaxClusterNumber()-NumberOfFreeClusters());
1.112 + }
1.113 +
1.114 +/**
1.115 + Write a value to the FAT (indirection table)
1.116 +
1.117 + @param aFatIndex Cluster to write to
1.118 + @param aValue value to write to Fat
1.119 +*/
1.120 +void CRamFatTable::WriteL(TUint32 aFatIndex, TUint32 aValue)
1.121 + {
1.122 + //__PRINT(_L("CRamFatTable::WriteL"));
1.123 +
1.124 +// __ASSERT_ALWAYS(aFatIndex>=2 && (aValue>=2 || aValue==0) && aValue<=0xFFFF,User::Leave(KErrCorrupt));
1.125 + TUint32 indirectCluster=aFatIndex;
1.126 + TUint32 indirectClusterNewVal=0;
1.127 + ReadIndirectionTable(indirectCluster);
1.128 +// If value in indirection table!=0 we assume we have already written to the indirection table
1.129 +// So just update the FAT table
1.130 + if (indirectCluster!=0 && aValue!=0)
1.131 + {
1.132 + WriteFatTable(aFatIndex,aValue);
1.133 + return;
1.134 + }
1.135 +// If value in indirection table is 0, we haven't written to it yet, though the memory has
1.136 +// already been allocated by the EnlargeL() function
1.137 + if (indirectCluster==0 && aValue!=0) // Assumes memory has already been allocated
1.138 + indirectClusterNewVal=AllocateClusterNumber();
1.139 +// Write aValue into aFaxIndex and indirectClusterNewVal into the corresponding position
1.140 +// in the indirection table
1.141 + WriteFatTable(aFatIndex,aValue,indirectClusterNewVal);
1.142 + }
1.143 +
1.144 +/**
1.145 + Read the value of a cluster in the Fat
1.146 +
1.147 + @param aFatIndex A cluster to read
1.148 + @return The cluster value read
1.149 +*/
1.150 +TUint32 CRamFatTable::ReadL(TUint32 aFatIndex) const
1.151 + {
1.152 + __ASSERT_ALWAYS(aFatIndex>=KFatFirstSearchCluster,User::Leave(KErrCorrupt));
1.153 +
1.154 + TUint32 clusterVal;
1.155 +
1.156 + switch(FatType())
1.157 + {
1.158 + case EFat16:
1.159 + clusterVal=*(TUint16*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos);
1.160 + break;
1.161 +
1.162 + case EFat32:
1.163 + clusterVal=*(TUint32*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos);
1.164 + break;
1.165 +
1.166 + default:
1.167 + ASSERT(0);
1.168 + return 0;
1.169 + }
1.170 +
1.171 + return clusterVal;
1.172 + }
1.173 +
1.174 +/**
1.175 + Write a value to the FAT and indirection table
1.176 +
1.177 + @param aFatIndex Cluster number to write to
1.178 + @param aFatValue Cluster value for Fat
1.179 + @param anIndirectionValue Value for indirection table
1.180 +*/
1.181 +void CRamFatTable::WriteFatTable(TInt aFatIndex,TInt aFatValue,TInt anIndirectionValue)
1.182 + {
1.183 + const TUint8* pos=RamDiskBase()+PosInBytes(aFatIndex);
1.184 +
1.185 + switch(FatType())
1.186 + {
1.187 + case EFat16:
1.188 + *(TUint16*)(pos+iFatTablePos)=(TUint16)aFatValue;
1.189 + *(TUint16*)(pos+iIndirectionTablePos)=(TUint16)anIndirectionValue;
1.190 + break;
1.191 +
1.192 + case EFat32:
1.193 + *(TUint32*)(pos+iFatTablePos)=(TUint32)aFatValue;
1.194 + *(TUint32*)(pos+iIndirectionTablePos)=(TUint32)anIndirectionValue;
1.195 + break;
1.196 +
1.197 + default:
1.198 + ASSERT(0);
1.199 + return;
1.200 + }
1.201 +
1.202 + }
1.203 +
1.204 +/**
1.205 + Write to just the fat table
1.206 +
1.207 + @param aFatIndex Cluster number to write to
1.208 + @param aFatValue Cluster value for Fat
1.209 +*/
1.210 +void CRamFatTable::WriteFatTable(TInt aFatIndex,TInt aFatValue)
1.211 + {
1.212 +
1.213 + switch(FatType())
1.214 + {
1.215 + case EFat16:
1.216 + *(TUint16*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos)=(TUint16)aFatValue;
1.217 + break;
1.218 +
1.219 + case EFat32:
1.220 + *(TUint32*)(RamDiskBase()+PosInBytes(aFatIndex)+iFatTablePos)=(TUint32)aFatValue;
1.221 + break;
1.222 +
1.223 + default:
1.224 + ASSERT(0);
1.225 + return;
1.226 + }
1.227 +
1.228 + }
1.229 +
1.230 +/**
1.231 + Write to just the fat table
1.232 +
1.233 + @param aFatIndex Cluster number to write to
1.234 + @param aFatValue Value for indirection table
1.235 +*/
1.236 +void CRamFatTable::WriteIndirectionTable(TInt aFatIndex,TInt aFatValue)
1.237 + {
1.238 + switch(FatType())
1.239 + {
1.240 + case EFat16:
1.241 + *(TUint16*)(RamDiskBase()+PosInBytes(aFatIndex)+iIndirectionTablePos)=(TUint16)aFatValue;
1.242 + break;
1.243 +
1.244 + case EFat32:
1.245 + *(TUint32*)(RamDiskBase()+PosInBytes(aFatIndex)+iIndirectionTablePos)=(TUint32)aFatValue;
1.246 + break;
1.247 +
1.248 + default:
1.249 + ASSERT(0);
1.250 + return;
1.251 + }
1.252 + }
1.253 +
1.254 +/**
1.255 + Find the real location of aCluster
1.256 + @param aCluster Cluster to read, contians cluster value upon return
1.257 +*/
1.258 +void CRamFatTable::ReadIndirectionTable(TUint32& aCluster) const
1.259 + {
1.260 + switch(FatType())
1.261 + {
1.262 + case EFat16:
1.263 + aCluster=*(TUint16*)(RamDiskBase()+PosInBytes(aCluster)+iIndirectionTablePos);
1.264 + break;
1.265 +
1.266 + case EFat32:
1.267 + aCluster=*(TUint32*)(RamDiskBase()+PosInBytes(aCluster)+iIndirectionTablePos);
1.268 + break;
1.269 +
1.270 + default:
1.271 + ASSERT(0);
1.272 + return;
1.273 + }
1.274 +
1.275 + }
1.276 +
1.277 +/**
1.278 + Copy memory in RAM drive area, unlocking required
1.279 +
1.280 + @param aTrg Pointer to destination location
1.281 + @param aSrc Pointer to source location
1.282 + @param aLength Length of data to copy
1.283 + @return Pointer to end of data copied
1.284 +*/
1.285 +TUint8* CRamFatTable::MemCopy(TAny* aTrg,const TAny* aSrc,TInt aLength)
1.286 + {
1.287 + TUint8* p=Mem::Copy(aTrg,aSrc,aLength);
1.288 + return(p);
1.289 + }
1.290 +
1.291 +/**
1.292 + Copy memory with filling the source buffer with zeroes. Target and source buffers can overlap.
1.293 + Used on RAMDrive srinking in order to wipe data from the file that is being deleted.
1.294 +
1.295 + @param aTrg pointer to the target address
1.296 + @param aSrc pointer to the destination address
1.297 + @param aLength how many bytes to copy
1.298 + @return A pointer to a location aLength bytes beyond aTrg (i.e. the location aTrg+aLength).
1.299 +*/
1.300 +TUint8* CRamFatTable::MemCopyFillZ(TAny* aTrg, TAny* aSrc,TInt aLength)
1.301 +{
1.302 + //-- just copy src to the trg, the memory areas can overlap.
1.303 + TUint8* p=Mem::Copy(aTrg, aSrc, aLength);
1.304 +
1.305 + //-- now zero-fill the source memory area taking into account possible overlap.
1.306 + TUint8* pSrc = static_cast<TUint8*>(aSrc);
1.307 + TUint8* pTrg = static_cast<TUint8*>(aTrg);
1.308 +
1.309 + TUint8* pZFill = NULL; //-- pointer to the beginning of zerofilled area
1.310 + TInt zFillLen = 0; //-- a number of bytes to zero-fill
1.311 +
1.312 + if(aTrg < aSrc)
1.313 + {
1.314 + if(pTrg+aLength < pSrc)
1.315 + {//-- target and source areas do not overlap
1.316 + pZFill = pSrc;
1.317 + zFillLen = aLength;
1.318 + }
1.319 + else
1.320 + {//-- target and source areas overlap, try not to corrupt the target area
1.321 + zFillLen = pSrc-pTrg;
1.322 + pZFill = pTrg+aLength;
1.323 + }
1.324 + }
1.325 + else
1.326 + {
1.327 + if(pSrc+aLength < pTrg)
1.328 + {//-- target and source areas do not overlap
1.329 + pZFill = pSrc;
1.330 + zFillLen = aLength;
1.331 + }
1.332 + else
1.333 + {//-- target and source areas overlap, try not to corrupt the target area
1.334 + zFillLen = pSrc+aLength-pTrg;
1.335 + pZFill = pSrc;
1.336 + }
1.337 + }
1.338 +
1.339 + Mem::FillZ(pZFill, zFillLen);
1.340 +
1.341 + return(p);
1.342 +}
1.343 +
1.344 +
1.345 +/**
1.346 + Zero fill RAM area corresponding to the cluster number aCluster
1.347 + @param aCluster a cluster number to be zero-filled
1.348 +*/
1.349 +void CRamFatTable::ZeroFillCluster(TInt aCluster)
1.350 + {
1.351 + TLinAddr clusterPos= I64LOW(DataPositionInBytes(aCluster));
1.352 + Mem::FillZ(iRamDiskBase+clusterPos, 1<< iOwner->ClusterSizeLog2());
1.353 + }
1.354 +
1.355 +
1.356 +/**
1.357 +Return the location of a Cluster in the data section of the media
1.358 +
1.359 +@param aCluster to find location of
1.360 +@return Byte offset of the cluster data
1.361 +*/
1.362 +TInt64 CRamFatTable::DataPositionInBytes(TUint32 aCluster) const
1.363 + {
1.364 + //__PRINT(_L("CRamFatTable::DataPositionInBytes"));
1.365 + ReadIndirectionTable(aCluster);
1.366 + return(aCluster<<iOwner->ClusterSizeLog2());
1.367 + }
1.368 +
1.369 +//-----------------------------------------------------------------------------
1.370 +
1.371 +/**
1.372 + Allocate and link a cluster chain, leaves if there are not enough free clusters.
1.373 + Chain starts as close as possible to aNearestCluster, last cluster will be marked as EOF.
1.374 +
1.375 + @param aNumber Number of clusters to allocate
1.376 + @param aNearestCluster Cluster the new chain should be nearest to
1.377 + @leave System wide error codes
1.378 + @return The first cluster number allocated
1.379 +*/
1.380 +TUint32 CRamFatTable::AllocateClusterListL(TUint32 aNumber, TUint32 aNearestCluster)
1.381 + {
1.382 + __PRINT2(_L("CRamFatTable::AllocateClusterList() N:%d,NearestCL:%d"),aNumber,aNearestCluster);
1.383 + __ASSERT_DEBUG(aNumber>0, Fault(EFatBadParameter));
1.384 +
1.385 + if(!RequestFreeClusters(aNumber))
1.386 + {
1.387 + __PRINT(_L("CRamFatTable::AllocateClusterListL - leaving KErrDirFull"));
1.388 + User::Leave(KErrDiskFull);
1.389 + }
1.390 +
1.391 + //-- if this leaves for some reason, there will be no lost clusters
1.392 + TInt firstCluster = aNearestCluster = AllocateSingleClusterL(aNearestCluster);
1.393 +
1.394 +
1.395 + if (aNumber>1)
1.396 + {//-- if this part leaves (e.g. fail to expand the RAM drive), we will need to handle the first allocated EOC
1.397 + TRAPD(nRes, ExtendClusterListL(aNumber-1, (TInt&)aNearestCluster));
1.398 + if(nRes != KErrNone)
1.399 + {
1.400 + __PRINT1(_L("CRamFatTable::AllocateClusterListL:ExtendClusterListL() failed with %d") ,nRes);
1.401 + FreeClusterListL(firstCluster); //-- clean up EOC in firstCluster
1.402 + User::Leave(nRes);
1.403 + }
1.404 + }
1.405 +
1.406 +
1.407 + return firstCluster;
1.408 + }
1.409 +
1.410 +/**
1.411 +Allocate and mark as EOF a single cluster as close as possible to aNearestCluster,
1.412 +calls base class implementation but must Enlarge the RAM drive first. Allocated cluster RAM area will be zero-filled.
1.413 +
1.414 +@param aNearestCluster Cluster the new cluster should be nearest to
1.415 +@leave System wide error codes
1.416 +@return The cluster number allocated
1.417 +*/
1.418 +TUint32 CRamFatTable::AllocateSingleClusterL(TUint32 aNearestCluster)
1.419 + {
1.420 + __PRINT(_L("CRamFatTable::AllocateSingleClusterL"));
1.421 + iOwner->EnlargeL(1<<iOwner->ClusterSizeLog2()); // First enlarge the RAM drive
1.422 + TInt fileAllocated=CFatTable::AllocateSingleClusterL(aNearestCluster); // Now update the free cluster and fat/fit
1.423 + ZeroFillCluster(fileAllocated); //-- zero-fill allocated cluster
1.424 + return(fileAllocated);
1.425 + }
1.426 +
1.427 +
1.428 +/**
1.429 + Extend a file or directory cluster chain, enlarging RAM drive first. Allocated clusters are zero-filled.
1.430 + Leaves if there are no free clusters (the disk is full).
1.431 + Note that method now doesn't call CFatTable::ExtendClusterListL() from its base class, be careful making changes there.
1.432 +
1.433 + @param aNumber number of clusters to allocate
1.434 + @param aCluster starting cluster number / ending cluster number after
1.435 + @leave KErrDiskFull + system wide error codes
1.436 +*/
1.437 +void CRamFatTable::ExtendClusterListL(TUint32 aNumber, TInt& aCluster)
1.438 + {
1.439 + __PRINT2(_L("CRamFatTable::ExtendClusterListL(%d, %d)"), aNumber, aCluster);
1.440 + __ASSERT_DEBUG(aNumber>0,Fault(EFatBadParameter));
1.441 +
1.442 + iOwner->EnlargeL(aNumber<<iOwner->ClusterSizeLog2());
1.443 +
1.444 + while(aNumber && GetNextClusterL(aCluster))
1.445 + aNumber--;
1.446 +
1.447 + if(!aNumber)
1.448 + return;
1.449 +
1.450 + if (NumberOfFreeClusters() < aNumber)
1.451 + {
1.452 + __PRINT(_L("CRamFatTable::ExtendClusterListL - leaving KErrDirFull"));
1.453 + User::Leave(KErrDiskFull);
1.454 + }
1.455 +
1.456 + while(aNumber--)
1.457 + {
1.458 + const TInt freeCluster=FindClosestFreeClusterL(aCluster);
1.459 +
1.460 + WriteFatEntryEofL(freeCluster); // Must write EOF for FindClosestFreeCluster to work again
1.461 + DecrementFreeClusterCount(1);
1.462 + WriteL(aCluster,freeCluster);
1.463 + aCluster=freeCluster;
1.464 + ZeroFillCluster(freeCluster); //-- zero fill just allocated cluster (RAM area)
1.465 + }
1.466 +
1.467 + SetFreeClusterHint(aCluster);
1.468 +
1.469 + }
1.470 +
1.471 +/**
1.472 +Mark a chain of clusters as free in the FAT. Shrinks the RAM drive once the
1.473 +clusters are free
1.474 +
1.475 +@param aCluster Start cluster of cluster chain to free
1.476 +@leave System wide error codes
1.477 +*/
1.478 +void CRamFatTable::FreeClusterListL(TUint32 aCluster)
1.479 + {
1.480 + __PRINT1(_L("CRamFatTable::FreeClusterListL aCluster=%d"),aCluster);
1.481 + if (aCluster==0)
1.482 + return; // File has no cluster allocated
1.483 +
1.484 + const TInt clusterShift=iOwner->ClusterSizeLog2();
1.485 + TInt startCluster=aCluster;
1.486 + TInt endCluster=0;
1.487 + TInt totalFreed=0;
1.488 + TLinAddr srcEnd=0;
1.489 +
1.490 + if(IsFat32())
1.491 + {
1.492 + while(endCluster!=EOF_32Bit)
1.493 + {
1.494 + TInt num=CountContiguousClustersL(startCluster,endCluster,KMaxTInt);
1.495 + if (GetNextClusterL(endCluster)==EFalse || endCluster==0)
1.496 + endCluster=EOF_32Bit; // endCluster==0 -> file contained FAT loop
1.497 +
1.498 + // Real position in bytes of the start cluster in the data area
1.499 + TLinAddr startClusterPos=I64LOW(DataPositionInBytes(startCluster));
1.500 + // Sliding value when more than one block is freed
1.501 + TLinAddr trg=startClusterPos-(totalFreed<<clusterShift);
1.502 + __PRINT1(_L("trg=0x%x"),trg);
1.503 +
1.504 + // Beginning of data area to move
1.505 + TLinAddr srcStart=startClusterPos+(num<<clusterShift);
1.506 + __PRINT1(_L("srcStart=0x%x"),srcStart);
1.507 + // Position of next part of cluster chain or position of end of ram drive
1.508 + if (endCluster==EOF_32Bit) // Last cluster is the end of the chain
1.509 + {
1.510 +
1.511 +
1.512 + // Fixed to use the genuine RAM drive size rather than the number
1.513 + // of free clusters - though they *should* be the same
1.514 + // It avoids the problem of iFreeClusters getting out of sync with
1.515 + // the RAM drive size but doesn't solve the issue of why it can happen...
1.516 +
1.517 + srcEnd=I64LOW(iOwner->Size());
1.518 + __PRINT1(_L("srcEnd=0x%x"),srcEnd);
1.519 + }
1.520 + else // Just move up to the next part of the chain
1.521 + srcEnd=I64LOW(DataPositionInBytes(endCluster));
1.522 +
1.523 + //-- Copy (srcEnd-srcStart) bytes from iRamDiskBase+srcStart onto iRamDiskBase+trg
1.524 + //-- zero-filling free space to avoid leaving something important there
1.525 + ASSERT(srcEnd >= srcStart);
1.526 + if(srcEnd-srcStart > 0)
1.527 + {
1.528 + MemCopyFillZ(iRamDiskBase+trg,iRamDiskBase+srcStart,srcEnd-srcStart);
1.529 + }
1.530 + else
1.531 + {//-- we are freeing the cluster chain at the end of the RAM drive; Nothing to copy to the drive space that has become free,
1.532 + //-- but nevertheless zero fill this space.
1.533 + Mem::FillZ(iRamDiskBase+trg, num<<clusterShift);
1.534 + }
1.535 +
1.536 +
1.537 + totalFreed+=num;
1.538 + startCluster=endCluster;
1.539 + UpdateIndirectionTable(srcStart>>clusterShift,srcEnd>>clusterShift,totalFreed);
1.540 + }
1.541 + }
1.542 + else
1.543 + {
1.544 + while(endCluster!=EOF_16Bit)
1.545 + {
1.546 + TInt num=CountContiguousClustersL(startCluster,endCluster,KMaxTInt);
1.547 + if (GetNextClusterL(endCluster)==EFalse || endCluster==0)
1.548 + endCluster=EOF_16Bit; // endCluster==0 -> file contained FAT loop
1.549 +
1.550 + // Real position in bytes of the start cluster in the data area
1.551 + TLinAddr startClusterPos=I64LOW(DataPositionInBytes(startCluster));
1.552 + // Sliding value when more than one block is freed
1.553 + TLinAddr trg=startClusterPos-(totalFreed<<clusterShift);
1.554 + __PRINT1(_L("trg=0x%x"),trg);
1.555 +
1.556 + // Beginning of data area to move
1.557 + TLinAddr srcStart=startClusterPos+(num<<clusterShift);
1.558 + __PRINT1(_L("srcStart=0x%x"),srcStart);
1.559 + // Position of next part of cluster chain or position of end of ram drive
1.560 + if (endCluster==EOF_16Bit) // Last cluster is the end of the chain
1.561 + {
1.562 +
1.563 +
1.564 + // Fixed to use the genuine RAM drive size rather than the number
1.565 + // of free clusters - though they *should* be the same
1.566 + // It avoids the problem of iFreeClusters getting out of sync with
1.567 + // the RAM drive size but doesn't solve the issue of why it can happen...
1.568 +
1.569 + srcEnd=I64LOW(iOwner->Size());
1.570 + __PRINT1(_L("srcEnd=0x%x"),srcEnd);
1.571 + }
1.572 + else // Just move up to the next part of the chain
1.573 + srcEnd=I64LOW(DataPositionInBytes(endCluster));
1.574 +
1.575 + //-- Copy (srcEnd-srcStart) bytes from iRamDiskBase+srcStart onto iRamDiskBase+trg
1.576 + //-- zero-filling free space to avoid leaving something important there
1.577 + ASSERT(srcEnd >= srcStart);
1.578 + if(srcEnd-srcStart > 0)
1.579 + {
1.580 + MemCopyFillZ(iRamDiskBase+trg,iRamDiskBase+srcStart,srcEnd-srcStart);
1.581 + }
1.582 + else
1.583 + {//-- we are freeing the cluster chain at the end of the RAMdrive; Nothing to copy to the drive space that has become free,
1.584 + //-- but nevertheless zero fill this space.
1.585 + Mem::FillZ(iRamDiskBase+trg, num<<clusterShift);
1.586 + }
1.587 +
1.588 + totalFreed+=num;
1.589 + startCluster=endCluster;
1.590 + UpdateIndirectionTable(srcStart>>clusterShift,srcEnd>>clusterShift,totalFreed);
1.591 + }
1.592 + }
1.593 + TInt bytesFreed=totalFreed<<clusterShift;
1.594 +
1.595 +// First free the cluster list
1.596 + CFatTable::FreeClusterListL(aCluster);
1.597 +// Now reduce the size of the RAM drive
1.598 + iOwner->ReduceSizeL(srcEnd-bytesFreed,bytesFreed);
1.599 + }
1.600 +
1.601 +/**
1.602 +Shift any clusters between aStart and anEnd backwards by aClusterShift
1.603 +
1.604 +@param aStart Start of shift region
1.605 +@param anEnd End of shift region
1.606 +@param aClusterShift amount to shift cluster by
1.607 +*/
1.608 +void CRamFatTable::UpdateIndirectionTable(TUint32 aStart,TUint32 anEnd,TInt aClusterShift)
1.609 + {
1.610 + __PRINT(_L("CRamFatTable::UpdateIndirectionTable"));
1.611 +#if defined(__WINS__)
1.612 + TUint32 count=iOwner->MaxClusterNumber();
1.613 + while (count--)
1.614 + {
1.615 + TUint32 cluster=count;
1.616 + ReadIndirectionTable(cluster);
1.617 + if (cluster>=aStart && cluster<anEnd)
1.618 + WriteIndirectionTable(count,cluster-aClusterShift);
1.619 + }
1.620 +#else
1.621 + TUint16* table=(TUint16*)(RamDiskBase()+iIndirectionTablePos);
1.622 + TUint16* entry=table+iOwner->MaxClusterNumber();
1.623 + while (entry>table)
1.624 + {
1.625 + TUint32 cluster=*--entry;
1.626 + if (cluster<aStart)
1.627 + continue;
1.628 + if (cluster<anEnd)
1.629 + *entry=TUint16(cluster-aClusterShift);
1.630 + }
1.631 +#endif
1.632 + }
1.633 +
1.634 +
1.635 +