userlibandfileserver/fileserver/sfat/sl_check.cpp
changeset 0 a41df078684a
child 2 4122176ea935
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfat/sl_check.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,299 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32\sfat\sl_check.cpp
+// 
+//
+
+#include "sl_std.h"
+#include "sl_scandrv.h"
+
+const TInt KMaxBufferSize=8192;
+
+
+TBool CCheckFatTable::IsEof16Bit(TInt aCluster) const
+{
+    return(aCluster>=0xFFF8 && aCluster<=0xFFFF);
+}
+
+TBool CCheckFatTable::IsEof12Bit(TInt aCluster) const
+{
+    return(aCluster>=0xFF8 && aCluster<=0xFFF);
+}
+
+TInt CCheckFatTable::MaxFatIndex() const
+    {   
+	__ASSERT_DEBUG((TUint)iMaxFatIndex>=KFatFirstSearchCluster, Fault(ECheckFatIndexZero));
+	return(iMaxFatIndex);
+	}
+
+
+CCheckFatTable* CCheckFatTable::NewL(CFatMountCB* aOwner)
+//
+// Create a CCheckFatTable
+//
+	{
+	CCheckFatTable* fatTable;
+	fatTable=new(ELeave) CCheckFatTable(aOwner);
+	return(fatTable);
+	}
+
+
+CCheckFatTable::CCheckFatTable(CFatMountCB* aOwner)
+//
+// Constructor
+//
+	{
+	iOwner=aOwner;
+	}
+
+CCheckFatTable::~CCheckFatTable()
+//
+// Destructor
+//
+	{
+	User::Free(iCheckFat);
+	}
+
+
+void CCheckFatTable::InitializeL()
+//
+// Initialize the check fat table
+//
+	{
+	__PRINT(_L("CCheckFatTable::InitializeL"));
+
+	TInt fatSize=iOwner->FatSizeInBytes();
+
+	if(iCheckFat==NULL)
+		iCheckFat=(TUint8*)User::AllocL(fatSize);
+	else
+		iCheckFat=(TUint8*)User::ReAllocL(iCheckFat,fatSize);
+	Mem::FillZ(iCheckFat,fatSize);
+	iMaxFatIndex=iOwner->UsableClusters()+1;
+	if(iOwner->Is16BitFat())
+		{
+		__ASSERT_ALWAYS(iMaxFatIndex>0 && iMaxFatIndex<EOF_16Bit && !IsEof16Bit(iMaxFatIndex),User::Leave(KErrCorrupt));
+		}
+	else
+		{
+		__ASSERT_ALWAYS(iMaxFatIndex>0 && iMaxFatIndex<EOF_12Bit && !IsEof12Bit(iMaxFatIndex),User::Leave(KErrCorrupt));
+		}
+	WriteMediaDescriptor();
+	
+	__PRINT2(_L("fatSize=%d,iCheckFat=0x%x"),fatSize,iCheckFat);
+	}
+
+
+/**
+@return ETrue if found errors in FAT 
+*/
+TBool CCheckFatTable::FlushL()
+//
+// Flush iCheckFat to the media, comparing each sector to corresponding 
+// sector in all fats (cf.CFixedCache::FlushL)
+//	
+	{
+	TBool bErrFound = EFalse;
+    
+    __PRINT(_L("CCheckFatTable::FlushL()"));
+	HBufC8* hBuf=HBufC8::New(KMaxBufferSize);
+	if (hBuf==NULL)
+		hBuf=HBufC8::NewL(KMaxBufferSize/4);
+	CleanupStack::PushL(hBuf);
+
+	TUint8* ptr=(TUint8*)hBuf->Ptr();
+	TInt maxSize=hBuf->Des().MaxSize();
+
+	TPtr8 fatBuffer(ptr,maxSize);
+	TInt fatSize=iOwner->FatSizeInBytes();
+	TInt remainder=fatSize;
+	TInt offset=iOwner->StartOfFatInBytes();
+	TUint8* dataPtr=iCheckFat;
+    TFatDriveInterface& drive = iOwner->DriveInterface();
+	TInt fatNumber=iOwner->NumberOfFats();
+	
+	while(remainder)
+		{
+		TInt s=Min(fatBuffer.MaxSize(),remainder);
+		TInt fatCount=fatNumber;
+		TInt fatPos=0;
+		while(fatCount)
+			{
+			TInt fatOffset=offset+fatPos;
+			User::LeaveIfError(drive.ReadCritical(fatOffset,s,fatBuffer));
+			TInt rem2=s;
+			TInt offset2=fatOffset;
+			TUint8* dataPtr2=dataPtr;
+			TInt bufOffset=0;
+			while(rem2)
+				{
+				TInt s2=Min(rem2,512);
+				TInt r=Mem::Compare(dataPtr2,s2,fatBuffer.Ptr()+bufOffset,s2);
+				if (r!=0)
+					{
+					bErrFound = ETrue;
+                    TPtrC8 dataBuf(dataPtr2,s2);
+					User::LeaveIfError(drive.WriteCritical(offset2,dataBuf));
+					}
+				rem2-=s2;
+				offset2+=s2;
+				dataPtr2+=s2;
+				bufOffset+=s2;
+				}
+			--fatCount;
+			fatPos+=fatSize;
+			}
+		offset+=s;
+		dataPtr+=s;
+		remainder-=s;
+		}
+
+	CleanupStack::PopAndDestroy();
+
+    return bErrFound;
+	}
+
+void CCheckFatTable::WriteMediaDescriptor()
+//
+// Write media descriptor to first byte and 0xFF to
+// remaining bytes of first two entries
+//
+	{
+	__PRINT(_L("CCheckFatTable::WriteMediaDescriptor"));
+	iCheckFat[0]=KBootSectorMediaDescriptor;
+	iCheckFat[1]=0xFF;
+	iCheckFat[2]=0xFF;
+	if (iOwner->Is16BitFat())
+		iCheckFat[3]=0xFF;
+	}
+
+TInt CCheckFatTable::PosInBytes(TInt aFatIndex) const
+//
+// Return number of bytes into the fat
+//
+	{
+	TInt fatPosInBytes;
+	if (iOwner->Is16BitFat())
+		fatPosInBytes=aFatIndex<<1;
+	else
+		// this is used since 8-bit access will be used for reading/writing
+		fatPosInBytes=(aFatIndex*3>>1);
+	return(fatPosInBytes);
+	}
+
+
+TInt CCheckFatTable::PosInIndex(TInt aBytePos) const
+//
+// Return index given byte position in fat
+//
+	{
+	if(iOwner->Is16BitFat())
+		return(aBytePos>>1);
+	else
+		return((aBytePos<<1)/3);
+	}
+
+
+TInt CCheckFatTable::ReadL(TInt aFatIndex) const
+//
+// Read a value from the check fat
+//
+	{
+	__ASSERT_ALWAYS((TUint32)aFatIndex >=KFatFirstSearchCluster && aFatIndex<=MaxFatIndex(),User::Leave(KErrCorrupt));
+	TUint clusterVal;
+	if(iOwner->Is16BitFat())
+		clusterVal=*(TUint16*)(iCheckFat+PosInBytes(aFatIndex));
+	else
+		{
+		TUint8* pCluster=iCheckFat+PosInBytes(aFatIndex);
+		clusterVal=pCluster[0]|(pCluster[1]<<8);
+		TBool oddCluster=(aFatIndex)&1;
+		if(oddCluster)
+			clusterVal>>=4;
+		clusterVal&=0xFFF;
+		}
+	return(clusterVal);
+	}
+
+
+void CCheckFatTable::WriteL(TInt aFatIndex,TInt aValue)
+//
+// Write a value to the check fat
+//
+	{
+	if(iOwner->Is16BitFat())
+		__ASSERT_ALWAYS((TUint32)aFatIndex>=KFatFirstSearchCluster && aFatIndex<=MaxFatIndex() && aValue>=0 && aValue<=0xFFFF,User::Leave(KErrCorrupt));
+	else
+		__ASSERT_ALWAYS((TUint32)aFatIndex>=KFatFirstSearchCluster && aFatIndex<=MaxFatIndex() && aValue>=0 && aValue<=0xFFF,User::Leave(KErrCorrupt));
+	TUint8* p=(TUint8*)(iCheckFat+PosInBytes(aFatIndex));
+	if (iOwner->Is16BitFat())
+		{ 
+		*(TUint16*)p=(TUint16)aValue;
+		return;
+		}
+	TUint8 mask=0x0F;
+	TBool odd=(aFatIndex)&1;
+	TUint8 fatVal;
+	if(odd)
+		{
+		mask<<=4;
+		aValue<<=4;
+		fatVal=p[0];
+		fatVal&=~mask;
+		fatVal|=(TUint8)(aValue&0xFF);
+		p[0]=fatVal;
+		p[1]=(TUint8)(aValue>>8);
+		}
+	else
+		{
+		p[0]=(TUint8)(aValue&0xFF);
+		fatVal=p[1];
+		fatVal&=~mask;
+		fatVal|=(TUint8)(aValue>>8);
+		p[1]=fatVal;
+		}
+	return;
+	}
+	
+
+TBool CCheckFatTable::GetNextClusterL(TInt& aCluster) const
+//
+// Get the next cluster in the chain from the check fat.
+//
+    {
+	__PRINT(_L("CCheckFatTable::GetNextClusterL"));
+	TBool ret;
+	TInt nextCluster=ReadL(aCluster);
+	if (iOwner->Is16BitFat())
+		ret=!IsEof16Bit(nextCluster);
+	else
+		ret=!IsEof12Bit(nextCluster);
+	if (ret)
+		aCluster=nextCluster;
+	return(ret);
+	}
+
+void CCheckFatTable::WriteFatEntryEofFL(TInt aCluster)
+//
+// Write EOF to aCluster
+//
+	{
+	__PRINT(_L("CCheckFatTable::WriteFatEntryEofF"));
+	if (iOwner->Is16BitFat())
+		WriteL(aCluster,EOF_16Bit);
+	else
+		WriteL(aCluster,EOF_12Bit);
+	}
+
+