--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/sisfile/sisfield.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,375 @@
+/*
+* Copyright (c) 2004-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:
+* Definition of the Swi::Sis::CField
+*
+*/
+
+
+#include <e32std.h>
+#include "sisfieldtypes.h"
+#include "sisfield.h"
+#include "sisdataprovider.h"
+#include "sisinstallerrors.h"
+
+using namespace Swi::Sis;
+
+
+CField::~CField()
+ {
+ }
+
+CField::CField()
+ {
+
+ }
+
+void CField::ConstructL(MSisDataProvider& aDataProvider, TFieldType aFieldType, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ ReadTypeL(aDataProvider, aFieldType, aBytesRead, aTypeReadBehaviour);
+ ReadLengthL(aDataProvider, aBytesRead);
+ }
+
+void CField::ConstructL(TPtrProvider& aDataProvider, TFieldType aFieldType, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ ReadTypeL(aDataProvider, aFieldType, aBytesRead, aTypeReadBehaviour);
+ ReadLengthL(aDataProvider, aBytesRead);
+ }
+
+// see GT0188.251 Section 2.12.1.2
+void CField::ReadLengthL(MSisDataProvider& aDataProvider, TInt64& aBytesRead)
+ {
+ TUint32 length = 0;
+
+ // read the first length bytes from the field
+ CField::ReadTTypeL<TUint32>(aDataProvider,length, aBytesRead);
+
+ // MSB set in length means length is 63 bits not 31 bits
+ if (length & 0x80000000)
+ {
+ TUint32 high = 0;
+ TUint32 low = length; // the low bytes are the length we just read
+
+ // reset MSB bit in low bytes
+ low &= ~ 0x80000000;
+
+ // read high bytes
+ CField::ReadTTypeL<TUint32>(aDataProvider, high, aBytesRead);
+
+ // check if the LSB is set in the high bytes, this is actually the MSB of the low bytes
+ if(high & 1)
+ {
+ // carry bit back from LSB high bytes to MSB low bytes
+ low |= 0x80000000;
+ }
+
+ // clear LSB of high bytes and rotate right
+ high &= ~1;
+ high >>= 1;
+
+ iLength=MAKE_TINT64(high, low); // relies on TFieldLength being TInt64 typedef
+ iHeaderSize=sizeof(TInt32) * 3;
+ }
+ else
+ {
+ iLength=TFieldLength(TInt(length));
+ iHeaderSize=sizeof(TInt32) * 2;
+ }
+ }
+
+void CField::ReadTypeL(MSisDataProvider& aDataProvider, TFieldType aFieldType, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ if (aTypeReadBehaviour==EReadType)
+ {
+ // Read type
+ CField::ReadEnumL<TFieldType,TInt32>(aDataProvider, iType, aBytesRead);
+
+ if (iType != aFieldType)
+ {
+ User::Leave(KErrSISUnexpectedFieldType);
+ }
+ }
+ else
+ {
+ // Set type
+ iType=TFieldType(aFieldType);
+ }
+ }
+
+void CField::ReadLengthL(TPtrProvider& aDataProvider, TInt64& aBytesRead)
+ {
+ TUint32 length = 0;
+
+ // read the first length bytes from the field
+ CField::ReadTTypeL<TUint32>(aDataProvider,length, aBytesRead);
+
+ // MSB set in length means length is 63 bits not 31 bits
+ if (length & 0x80000000)
+ {
+ TUint32 high = 0;
+ TUint32 low = length; // the low bytes are the length we just read
+
+ // reset MSB bit in low bytes
+ low &= ~ 0x80000000;
+
+ // read high bytes
+ CField::ReadTTypeL<TUint32>(aDataProvider, high, aBytesRead);
+
+ // check if the LSB is set in the high bytes, this is actually the MSB of the low bytes
+ if(high & 1)
+ {
+ // carry bit back from LSB high bytes to MSB low bytes
+ low |= 0x80000000;
+ }
+
+ // clear LSB of high bytes and rotate right
+ high &= ~1;
+ high >>= 1;
+
+ iLength=MAKE_TINT64(high, low); // relies on TFieldLength being TInt64 typedef
+ iHeaderSize=sizeof(TInt32) * 3;
+ }
+ else
+ {
+ iLength=TFieldLength(TInt(length));
+ iHeaderSize=sizeof(TInt32) * 2;
+ }
+ }
+
+void CField::ReadTypeL(TPtrProvider& aDataProvider, TFieldType aFieldType, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ if (aTypeReadBehaviour==EReadType)
+ {
+ // Read type
+ CField::ReadEnumL<TFieldType,TInt32>(aDataProvider, iType, aBytesRead);
+
+ if (iType != aFieldType)
+ {
+ User::Leave(KErrSISUnexpectedFieldType);
+ }
+ }
+ else
+ {
+ // Set type
+ iType=TFieldType(aFieldType);
+ }
+ }
+
+EXPORT_C TFieldLength CField::Length() const
+ {
+ return iLength;
+ }
+
+TFieldType CField::FieldType() const
+ {
+ return iType;
+ }
+
+void CField::EnsureAlignedL(MSisDataProvider& aDataProvider, TInt64 aBytesConsumed, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ // It doesn't matter whether we're actually in an array or not for the
+ // padding size since the difference is 4 bytes (==0 mod 4)
+
+ TInt paddingBytes= HeaderSize() + Length() + PaddingSize() - aBytesConsumed - (aTypeReadBehaviour==EAssumeType ? 4 : 0);
+
+ // Tempering in SISX file may cause the padding bytes to be equal or more then 4 bytes
+ // but it can be strictly between 0 to 3 only.
+ // So we put a boundary here and if that fails we say corrupt sis file.
+ if (paddingBytes >=0 && paddingBytes <4)
+ {
+ TBuf8<4> padding;
+ CField::CheckedReadL(aDataProvider, padding, paddingBytes, aBytesRead);
+ }
+ else
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+
+void CField::CheckedReadL(MSisDataProvider& aDataProvider, TDes8& aBuffer, TInt64& aBytesRead)
+ {
+ User::LeaveIfError(aDataProvider.Read(aBuffer, aBuffer.Length()));
+ aBytesRead+=aBuffer.Length();
+ }
+
+void CField::CheckedReadL(MSisDataProvider& aDataProvider, TDes8& aBuffer, TInt aSize, TInt64& aBytesRead)
+ {
+ User::LeaveIfError(aDataProvider.Read(aBuffer, aSize));
+
+ if (aBuffer.Length() != aSize)
+ {
+ User::Leave(KErrSISFieldBufferTooShort);
+ }
+ aBytesRead+=aSize;
+ }
+
+void CField::SkipUnknownFieldsL(MSisDataProvider& aDataProvider, TInt64 aBytesConsumed, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ TInt64 skipSize=Length() - aBytesConsumed + HeaderSize() - (aTypeReadBehaviour==EAssumeType ? 4 : 0);
+
+ if (skipSize==0)
+ {
+ return;
+ }
+ else if (skipSize < 0)
+ {
+ // this means we have over-read by -skipSize bytes
+ TInt overRead=-skipSize;
+
+ // If we've only over-read into the padding then it's ok since an extra field
+ // may have been added where padding was before, we don't need to skip
+ // any unknown sisfields since we know we're into the padding
+ if (overRead <= PaddingSize())
+ {
+ return;
+ }
+
+ // otherwise it's an invalid sisfile.
+ User::Leave(KErrSISFieldLengthInvalid);
+ }
+
+ TInt64 curPos = 0;
+ User::LeaveIfError(aDataProvider.Seek(ESeekCurrent, curPos));
+ TInt64 newPos = skipSize;
+ User::LeaveIfError(aDataProvider.Seek(ESeekCurrent, newPos));
+ if (curPos + skipSize != newPos)
+ {
+ User::Leave(KErrSISFieldLengthInvalid);
+ }
+
+ aBytesRead += skipSize;
+ }
+
+
+void CField::CreateHeader(TFieldType aFieldType, TFieldLength aFieldLength, TDes8& aHeader)
+ {
+ aHeader.Zero();
+
+ // define the integer / buffer pair used to append TInt32 integers to the header
+ TUint32 value;
+ TPckg<TUint32> pckg(value);
+
+ // Append the field type to the header
+ value = static_cast<TUint32>(aFieldType);
+ aHeader.Append(pckg);
+
+ // get the high and low 32 bit parts of the length
+ TUint32 high = I64HIGH(aFieldLength);
+ TUint32 low = I64LOW(aFieldLength);
+
+ // If it's >= 2 ^ 31 it will need to be written to the file in two 32 bit parts
+ if(high != 0 || low & 0x80000000)
+ {
+ // rotate the high value left ready to carry the bit 31 value from low
+ high <<= 1;
+ if(low & 0x80000000)
+ {
+ // carry from low if necessary
+ high |= 1;
+ }
+
+ // number is > 2^31 so must set MSB to flag this
+ low |= 0x80000000;
+
+ // append low 32 bits
+ value = low;
+ aHeader.Append(pckg);
+
+ // append high 32 bits
+ value = high;
+ aHeader.Append(pckg);
+ }
+ else
+ {
+ // it's less than 2^31 so we can write it out in one TInt32
+ value = low;
+ aHeader.Append(pckg);
+ }
+ }
+
+void CField::CalculateCrcL(MSisDataProvider& aDataProvider, const TInt64 aMaxLength, TUint16& aCrc)
+ {
+ // This function may appear inefficient but the data for which
+ // a CRC is calculated is not all in memory so reading from the
+ // data provider is somewhat inevitable
+ TBuf8 <512> buffer;
+ TInt length = 0;
+ TInt readLength = buffer.MaxLength();
+
+ // Do the CRC calculation for the data
+ while(length < aMaxLength)
+ {
+ buffer.Zero();
+ if(length + buffer.MaxLength() > aMaxLength)
+ {
+ readLength = aMaxLength - length;
+ }
+ User::LeaveIfError(aDataProvider.Read(buffer, readLength));
+
+ // If EOF is reached before aMaxLength has been read, the
+ // length specified in the header is incorrect.
+ if (buffer.Length() == 0)
+ {
+ User::Leave(KErrSISFieldLengthInvalid);
+ }
+ length += buffer.Length();
+ Mem::Crc(aCrc, buffer.Ptr(), buffer.Length());
+ }
+
+ // Do CRC of any padding
+ TUint8 padding[4] = { 0, 0, 0, 0 };
+ Mem::Crc(aCrc, padding, aMaxLength % 4);
+ }
+
+void CField::EnsureAlignedL(TPtrProvider& aDataProvider, TInt64 aBytesConsumed, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ // It doesn't matter whether we're actually in an array or not for the
+ // padding size since the difference is 4 bytes (==0 mod 4)
+
+ TInt paddingBytes= HeaderSize() + Length() + PaddingSize() - aBytesConsumed - (aTypeReadBehaviour==EAssumeType ? 4 : 0);
+ if (paddingBytes)
+ {
+ aDataProvider.ReadL(paddingBytes);
+ aBytesRead += paddingBytes;
+ }
+ }
+
+void CField::SkipUnknownFieldsL(TPtrProvider& aDataProvider, TInt64 aBytesConsumed, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour)
+ {
+ TInt64 skipSize=Length() - aBytesConsumed + HeaderSize() - (aTypeReadBehaviour==EAssumeType ? 4 : 0);
+
+ if (skipSize==0)
+ {
+ return;
+ }
+ else if (skipSize < 0)
+ {
+ // this means we have over-read by -skipSize bytes
+ TInt overRead=-skipSize;
+
+ // If we've only over-read into the padding then it's ok since an extra field
+ // may have been added where padding was before, we don't need to skip
+ // any unknown sisfields since we know we're into the padding
+ if (overRead <= PaddingSize())
+ {
+ return;
+ }
+
+ // otherwise it's an invalid sisfile.
+ User::Leave(KErrSISFieldLengthInvalid);
+ }
+
+ aDataProvider.ReadL(skipSize);
+ aBytesRead += skipSize;
+ }