diff -r 000000000000 -r 6a9f87576119 filemanager/bkupengine/src/MMCScBkupArchiveUtils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filemanager/bkupengine/src/MMCScBkupArchiveUtils.cpp Mon Jan 18 20:09:41 2010 +0200 @@ -0,0 +1,709 @@ +/* +* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: MMCScBkupArchiveUtils implementation +* +* +*/ + +#include "MMCScBkupArchiveUtils.h" + +// System includes +#include +#include + +// User includes +#include "MMCScBkupLogger.h" +#include "MMCScBkupDllUids.h" +#include "MMCScBkupPhoneModelUtils.h" +#include "CMMCScBkupArchiveFooter.h" +#include "CMMCScBkupArchiveHeader.h" +#include "MMMCScBkupArchiveDataInterface.h" +#include "MMCScBkupArchiveFlags.h" + +// Constants +const TInt8 KMMCScBkupArchiveFileFormatVersionMajor = 1; +#ifdef RD_FILE_MANAGER_BACKUP +const TInt8 KMMCScBkupArchiveFileFormatVersionMinor = 1; +#else +const TInt8 KMMCScBkupArchiveFileFormatVersionMinor = 0; +#endif +const TInt16 KMMCScBkupArchiveFileFormatVersionBuild = 1; +const TUid KMMCScBkupArchiveFileFormatUid1 = { KMMCAppEngUID3 }; +const TUid KMMCScBkupArchiveFileFormatUid2 = { 0 }; +const TUid KMMCScBkupArchiveFileFormatUid3 = { 0x0BACCCCC }; // FIX + + /** + * Fixed Header + * ============ + * + * 12 bytes = 3 uids + * 4 bytes = 1 uid crc checksum + * + * ARCHIVE FILE FORMAT VERSION + * { + * 1 byte = version major + * 1 byte = version minor + * 2 bytes = version build + * } + * + * 4 bytes = size of footer in bytes - this is always the same + * fixed length, hence we can write the size here. + * The value can then be used to work from the back of the + * archive to the starting position of the footer (where + * most of the juicy info is). + * + * 4 bytes = archive flags + * + * 4 bytes = archive payload CRC (activated when RD_FILE_MANAGER_BACKUP) + * + * 4 bytes = archive category + * + * 4 bytes = archive header CRC (activated when RD_FILE_MANAGER_BACKUP) + * + * KMMCScSpareByteCount bytes = spare padding + * + * 1 byte = phone model version string length + * n bytes = phone model version string + * + * + * + * Note that we deliberately do not use the streaming chevrons + * as we then risk the problem of running the string through + * a unicode compressor first. + */ + + +// ========================= MEMBER FUNCTIONS ================================ + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ArchiveUidType() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::ArchiveUidType(TUidType& aType) + { + aType = TUidType( KMMCScBkupArchiveFileFormatUid1, + KMMCScBkupArchiveFileFormatUid2, + KMMCScBkupArchiveFileFormatUid3 ); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ArchiveCheckedUid() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::ArchiveCheckedUid(TCheckedUid& aCheckedUids) + { + TUidType uidType; + ArchiveUidType( uidType ); + aCheckedUids.Set( uidType ); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::PhoneModelFromArchiveLC() +// +// +// --------------------------------------------------------------------------- +HBufC8* MMCScBkupArchiveUtils::PhoneModelFromArchiveLC( MMMCScBkupArchiveDataInterface& aADI ) + { + const TInt phoneModelOffset = OffsetOfModelInformation(); + // + RReadStream stream( aADI.ADIReadStreamUncompressedLC( phoneModelOffset ) ); + HBufC8* modelInfo = PhoneModelFromArchiveLC( stream); + CleanupStack::PopAndDestroy(); // stream + // + return modelInfo; + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ReadPhoneValidityInformationL() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::ReadPhoneValidityInformationL( RFs& aFsSession, const TDesC& aFileName, HBufC8*& aPhoneModelData, TBitFlags& aArchiveFlags, TVersion& aArchiveVersion ) + { + __ASSERT_DEBUG( aPhoneModelData == NULL, User::Invariant() ); + // + RFile64 file; + TInt error = file.Open( aFsSession, aFileName, EFileShareReadersOnly | EFileStream | EFileRead ); + User::LeaveIfError( error ); + CleanupClosePushL(file); + + // First, read the archive flags + aArchiveFlags = ReadArchiveFlagsL( file ); + + // Read version + ReadArchiveVersionL( file, aArchiveVersion ); + + // Then, create a stream interface to the file + const TInt phoneModelOffset = OffsetOfModelInformation(); + RFileReadStream stream( file, phoneModelOffset ); + CleanupStack::Pop( &file ); + CleanupClosePushL( stream ); // stream takes ownership of the file now + // + HBufC8* modelInfo = PhoneModelFromArchiveLC( stream ); + + // Unfortunately we have to juggle the cleanup stack + CleanupStack::Pop( modelInfo ); + CleanupStack::PopAndDestroy( &stream ); // also closes the file + + // Done + aPhoneModelData = modelInfo; + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ArchiveRunTimeFileFormatVersion() +// +// +// --------------------------------------------------------------------------- +TVersion MMCScBkupArchiveUtils::ArchiveRunTimeFileFormatVersion() + { + return TVersion( KMMCScBkupArchiveFileFormatVersionMajor, + KMMCScBkupArchiveFileFormatVersionMinor, + KMMCScBkupArchiveFileFormatVersionBuild ); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::WriteHeaderL() +// +// +// --------------------------------------------------------------------------- +const TMMCScBkupArchiveVector& MMCScBkupArchiveUtils::WriteHeaderL( MMMCScBkupArchiveDataInterface& aADI, + TBitFlags aCategory ) + { + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - START"); + RWriteStream stream( aADI.ADIWriteStreamUncompressedLC() ); + + // 16 bytes = uids + *uid* checksum + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [16] write uids + checksum"); + TCheckedUid checkedUid; + ArchiveCheckedUid( checkedUid ); + const TPtrC8 pUidAndCRC( checkedUid.Des() ); + stream.WriteL( pUidAndCRC ); + + // 4 bytes = file format version + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 4] write version"); + const TVersion version( ArchiveRunTimeFileFormatVersion() ); + stream.WriteInt8L( version.iMajor ); + stream.WriteInt8L( version.iMinor ); + stream.WriteInt16L( version.iBuild ); + + // 4 bytes = Footer length - starts life as length of 0, and + // is then written to again later on after the footer has + // been exteranlised. + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 4] write size of footer (starts life as 0)"); + const TInt footerLength = 0; + stream.WriteInt32L( footerLength ); + + // 4 bytes = Archive flags + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 4] archive flags (archive starts life invalid)"); + const TUint32 defaultArchiveFlags = DefaultArchiveFlags(); + stream.WriteUint32L( defaultArchiveFlags ); + + // 4 bytes = Initial payload CRC value, this will be updated with the final + // CRC once the entire archive has been prepared. + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 4] archive payload CRC"); + const TUint32 initialPayloadCRC = 0; + stream.WriteUint32L( initialPayloadCRC ); + + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 4] archive category"); + stream.WriteUint32L( aCategory.iFlags ); + + // 4 bytes = Initial header CRC value, this will be updated with the final + // CRC once the entire archive has been prepared. + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 4] archive header CRC"); + const TUint32 initialHeaderCRC = 0; + stream.WriteUint32L( initialHeaderCRC ); + + // KMMCScSpareByteCount = padding, for future use + __LOG1("MMCScBkupArchiveUtils::WriteHeaderL() - [%d] padding/spare data", KMMCScSpareByteCount); + for(TInt i = 0; i < KMMCScSpareByteCount/sizeof(TInt32); i++) + { + stream.WriteInt32L( 0 ); + } + + // 1 byte = Phone model version string length + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [ 1] phone model length"); + HBufC8* phoneModelString = MMCScBkupPhoneModelUtils::CurrentPhoneModelLC(); + stream.WriteInt8L( phoneModelString->Length() ); + + // Then the version string itself + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - [??] phone model string"); + stream.WriteL( *phoneModelString ); + + // Tidy up + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - committing stream..."); + stream.CommitL(); + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - destroying stream..."); + CleanupStack::PopAndDestroy( 2 ); // phoneModelString and stream + + __LOG("MMCScBkupArchiveUtils::WriteHeaderL() - END"); + return aADI.ADICurrentArchiveVectorInfo(); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ReadHeaderL() +// +// +// --------------------------------------------------------------------------- +const TMMCScBkupArchiveVector& MMCScBkupArchiveUtils::ReadHeaderL( MMMCScBkupArchiveDataInterface& aADI, CMMCScBkupArchiveHeader& aHeader ) + { + __LOG("MMCScBkupArchiveUtils::ReadHeaderL() - START"); + RReadStream stream( aADI.ADIReadStreamUncompressedLC() ); + + // 16 bytes = uids + *uid* checksum + TBuf8<16> uidBuffer; + stream.ReadL( uidBuffer, uidBuffer.MaxLength() ); + + // Create a UID type objjec + TCheckedUid checkedUid( uidBuffer ); + const TUidType uids( checkedUid.UidType()) ; + __LOG3("MMCScBkupArchiveUtils::ReadHeaderL() - uids: 0x%08x/0x%08x/0x%08x", uids[0], uids[1], uids[2] ); + if ( uids[0] == KNullUid && uids[1] == KNullUid && uids[2] == KNullUid ) + { + // Apparently, TCheckedUid sets the uids to 0 when the CRC doesn't match + // the value read from the file. + User::Leave( KErrNotSupported ); + } + aHeader.SetCheckedUid( checkedUid ); + + // 4 bytes = file format version + TVersion version; + version.iMajor = stream.ReadInt8L(); + version.iMinor = stream.ReadInt8L(); + version.iBuild = stream.ReadInt16L(); + aHeader.SetVersion( version ); + __LOG3("MMCScBkupArchiveUtils::ReadHeaderL() - version: %3d.%3d.%6d", version.iMajor, version.iMinor, version.iBuild ); + + // 4 bytes = Length of footer + const TInt footerLength = stream.ReadInt32L(); + aHeader.SetFooterLength( footerLength ); + __LOG1("MMCScBkupArchiveUtils::ReadHeaderL() - footerLength: %d", footerLength); + + // 4 bytes = Archive flags + const TUint32 archiveFlags = stream.ReadUint32L(); + aHeader.SetArchiveFlags( archiveFlags ); + __LOG1("MMCScBkupArchiveUtils::ReadHeaderL() - archiveFlags: %d", archiveFlags); + + // 4 bytes = Archive payload CRC + const TUint32 payloadCRC = stream.ReadUint32L(); + __LOG1("MMCScBkupArchiveUtils::ReadHeaderL() - archive payload CRC: %d", payloadCRC); + + // 4 bytes = Archive Category + const TUint32 archiveCategory = stream.ReadUint32L(); + __LOG1("MMCScBkupArchiveUtils::ReadHeaderL() - archiveCategory: %d", archiveCategory); + + // 4 bytes = Archive header CRC + const TUint32 headerCRC = stream.ReadUint32L(); + __LOG1("MMCScBkupArchiveUtils::ReadHeaderL() - archive header CRC: %d", headerCRC); + + // KMMCScSpareByteCount of padding (spare) data. Skip for now + for(TInt i = 0; i < KMMCScSpareByteCount/sizeof(TInt32); i++) + { + (void) stream.ReadInt32L(); + } + + // Then the version string itself - which is handled through a separate method: + HBufC8* phoneModel = PhoneModelFromArchiveLC( stream ); + aHeader.SetPhoneModelIdentifierL( *phoneModel ); + CleanupStack::PopAndDestroy( phoneModel ); + + // Clean up + CleanupStack::PopAndDestroy(); // stream + + __LOG("MMCScBkupArchiveUtils::ReadHeaderL() - END"); + return aADI.ADICurrentArchiveVectorInfo(); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::OffsetOfModelInformation() +// +// +// --------------------------------------------------------------------------- +TInt MMCScBkupArchiveUtils::OffsetOfModelInformation() + { + return EArchiveOffsetPhoneModelStringLength; + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::PhoneModelFromArchiveLC() +// +// +// --------------------------------------------------------------------------- +HBufC8* MMCScBkupArchiveUtils::PhoneModelFromArchiveLC( RReadStream& aStream ) + { + const TInt length = aStream.ReadInt8L(); + + // Validate against preconditions + const TInt maxLength = MMCScBkupPhoneModelUtils::MaximumPhoneModelIdentifierLength(); + if ( length > maxLength || length < 0 ) + { + User::Leave( KErrCorrupt ); + } + + // Now try to read the model identifier + HBufC8* model = HBufC8::NewLC( length ); + TPtr8 pModel( model->Des() ); + aStream.ReadL( pModel, length ); + + // All done + return model; + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::DefaultArchiveFlags() +// +// +// --------------------------------------------------------------------------- +TUint32 MMCScBkupArchiveUtils::DefaultArchiveFlags() + { + return EMMCScBkupArchiveFlagsDefault; + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::SetArchiveContentAsValidL() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::SetArchiveContentAsValidL( RFile64& aArchive ) + { + TInt error = KErrNone; + + // Calculate the offset to the archive flags: + const TUint archiveFlagsFileOffset = EArchiveOffsetArchiveFlags; + + // Flags are four bytes. Read the existing raw flag data + TBuf8< KMMCScArchiveFlagsByteCount > flagData; + error = aArchive.Read( static_cast( archiveFlagsFileOffset ), flagData ); + User::LeaveIfError( error ); + + // Interpret the flag data as real flags + RDesReadStream readStream( flagData ); + CleanupClosePushL( readStream ); + TUint32 archiveFlags = readStream.ReadUint32L(); + CleanupStack::PopAndDestroy( &readStream ); + + // Twiddle the "archive is complete/valid" bits + archiveFlags |= EMMCScBkupArchiveFlagsContentValid; + + // Write the flags back out the descriptor + flagData.Zero(); + RDesWriteStream writeStream( flagData ); + CleanupClosePushL( writeStream ); + writeStream.WriteUint32L( archiveFlags ); + writeStream.CommitL(); + CleanupStack::PopAndDestroy( &writeStream ); + + // Then write them to the file itself + error = aArchive.Write( static_cast( archiveFlagsFileOffset ), flagData ); + User::LeaveIfError( error ); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::SetFooterLengthL() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::SetFooterLengthL( RFile64& aArchive, TInt aLength ) + { + TInt error = KErrNone; + + // Calculate the offset to the footer length: + const TUint archiveFooterLengthOffset = EArchiveOffsetFooterLength; + + // Prepare externalized representation of length + TBuf8< KMMCScArchiveFooterLengthByteCount > footerLengthData; + RDesWriteStream writeStream( footerLengthData ); + CleanupClosePushL( writeStream ); + writeStream.WriteInt32L( aLength ); + writeStream.CommitL(); + CleanupStack::PopAndDestroy( &writeStream ); + + // Then write them to the file itself + error = aArchive.Write( static_cast( archiveFooterLengthOffset ), footerLengthData ); + User::LeaveIfError( error ); + } + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ReadBkUpCategoryInformationL() +// +// +// --------------------------------------------------------------------------- +TBitFlags MMCScBkupArchiveUtils::ReadBkUpCategoryInformationL( RFs& aFsSession, const TDesC& aFileName ) + { + RFile64 file; + TInt error = file.Open( aFsSession, aFileName, EFileShareReadersOnly | EFileStream | EFileRead ); + User::LeaveIfError( error ); + CleanupClosePushL(file); + + // Then, create a stream interface to the file + RFileReadStream stream( file, EArchiveOffsetArchiveCategory ); + CleanupStack::Pop( &file ); + CleanupClosePushL( stream ); // stream takes ownership of the file now + // + TUint category = stream.ReadUint32L(); + + CleanupStack::PopAndDestroy( &stream ); // also closes the file + + TBitFlags ret; + ret.SetValue( category ); + + return ret; + } + + +#ifdef RD_FILE_MANAGER_BACKUP +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::SetArchiveCrcsL() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::SetArchiveCrcsL( RFile64& aArchive, TUint32 aCrc ) + { + TInt error = KErrNone; + + // Payload crc + SetArchiveCrcL( aArchive, aCrc, EArchiveOffsetArchivePayloadCRC ); + + // Calculate and write header crc also to the file + TBuf8< KMMCScArchivePhoneModelStringLength > length; + TUint32 modelLength; + TUint32 headerCrc = 0; + + error = aArchive.Read( static_cast( EArchiveOffsetPhoneModelStringLength ), length ); + User::LeaveIfError(error); + RDesReadStream readStream( length ); + CleanupClosePushL( readStream ); + modelLength = readStream.ReadUint8L(); + CleanupStack::PopAndDestroy( &readStream ); + + CalculateCrcFromArchive( headerCrc, aArchive, 0, EArchiveOffsetArchiveHeaderCRC); + CalculateCrcFromArchive( headerCrc, aArchive, EArchiveOffsetArchiveHeaderCRC + KMMCScArchiveCrcByteCount, + KMMCScSpareByteCount + KMMCScArchivePhoneModelStringLength + modelLength); + SetArchiveCrcL( aArchive, headerCrc, EArchiveOffsetArchiveHeaderCRC ); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ValidateArchiveCrcsL() +// +// +// --------------------------------------------------------------------------- +TBool MMCScBkupArchiveUtils::ValidateArchiveCrcsL( RFs& aFsSession, const TDesC& aFileName ) + { + TBool validCrc = EFalse; + + RFile64 file; + TInt64 size; + + TInt error = file.Open( aFsSession, aFileName, EFileShareReadersOnly | EFileRead ); + + if ( error == KErrNone && file.Size(size) == KErrNone) + { + TBuf8< KMMCScArchiveFlagsByteCount > headerCrc; + TBuf8< KMMCScArchiveFlagsByteCount > payloadCrc; + TBuf8< KMMCScArchivePhoneModelStringLength > length; + TUint32 archivedHeaderCrc, calculatedHeaderCrc; + TUint32 archivedPayloadCrc, calculatedPayloadCrc; + TUint32 modelLength; + + // Read crcs from header + error = file.Read( static_cast( EArchiveOffsetArchiveHeaderCRC ), headerCrc ); + User::LeaveIfError(error); + error = file.Read( static_cast( EArchiveOffsetArchivePayloadCRC ), payloadCrc ); + User::LeaveIfError(error); + error = file.Read( static_cast( EArchiveOffsetPhoneModelStringLength ), length ); + User::LeaveIfError(error); + CleanupClosePushL( file ); + + RDesReadStream readStream( headerCrc ); + CleanupClosePushL( readStream ); + archivedHeaderCrc = readStream.ReadUint32L(); + readStream.Close(); + readStream.Open(payloadCrc); + archivedPayloadCrc = readStream.ReadUint32L(); + readStream.Close(); + readStream.Open(length); + modelLength = readStream.ReadUint8L(); + CleanupStack::PopAndDestroy( &readStream ); + + // Calculate crc from header in two parts + calculatedHeaderCrc = 0; + CalculateCrcFromArchive( calculatedHeaderCrc, file, 0, EArchiveOffsetArchiveHeaderCRC); + CalculateCrcFromArchive( calculatedHeaderCrc, file, EArchiveOffsetArchiveHeaderCRC + KMMCScArchiveCrcByteCount, + KMMCScSpareByteCount + KMMCScArchivePhoneModelStringLength + modelLength); + + // Calculate crc from payload and footer + TInt payloadSize = size - (EArchiveOffsetPhoneModelString + modelLength); + calculatedPayloadCrc = 0; + CalculateCrcFromArchive( calculatedPayloadCrc, file, EArchiveOffsetPhoneModelString + modelLength, payloadSize); + + if(archivedPayloadCrc == calculatedPayloadCrc && archivedHeaderCrc == calculatedHeaderCrc) + { + validCrc = ETrue; + } + else + { + __LOG4("MMCScBkupArchiveUtils::ValidateArchiveCrcsL() - crc mismatch: %u vs. %u - %u vs. %u", + archivedPayloadCrc, calculatedPayloadCrc, archivedHeaderCrc, calculatedHeaderCrc); + } + + CleanupStack::PopAndDestroy( &file ); + } + + return validCrc; + } +#endif // RD_FILE_MANAGER_BACKUP + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ReadArchiveFlagsL() +// +// +// --------------------------------------------------------------------------- +TBitFlags MMCScBkupArchiveUtils::ReadArchiveFlagsL( RFile64& aArchive ) + { + TInt error = KErrNone; + + // Calculate the offset to the archive flags: + const TUint archiveFlagsFileOffset = EArchiveOffsetArchiveFlags; + + // Flags are four bytes. Read the existing raw flag data + TBuf8< KMMCScArchiveFlagsByteCount > flagData; + error = aArchive.Read( static_cast( archiveFlagsFileOffset ), flagData ); + User::LeaveIfError( error ); + + // Interpret the flag data as real flags + RDesReadStream readStream( flagData ); + CleanupClosePushL( readStream ); + TUint32 archiveFlags = readStream.ReadUint32L(); + CleanupStack::PopAndDestroy( &readStream ); + + // Done + TBitFlags ret; + ret.SetValue( archiveFlags ); + return ret; + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::ReadArchiveVersionL() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::ReadArchiveVersionL( RFile64& aArchive, TVersion& aVersion ) + { + TInt error = KErrNone; + + // Calculate the offset to the archive flags: + const TUint archiveVersionFileOffset = EArchiveOffsetFileFormatVersion; + + // Flags are four bytes. Read the existing raw flag data + TBuf8< KMMCScArchiveVersionByteCount > versionData; + error = aArchive.Read( static_cast( archiveVersionFileOffset ), versionData ); + User::LeaveIfError( error ); + + // Interpret the flag data as real flags + RDesReadStream readStream( versionData ); + CleanupClosePushL( readStream ); + aVersion.iMajor = readStream.ReadInt8L(); + aVersion.iMinor = readStream.ReadInt8L(); + aVersion.iBuild = readStream.ReadInt16L(); + CleanupStack::PopAndDestroy( &readStream ); + } + + +#ifdef RD_FILE_MANAGER_BACKUP +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::SetArchiveCrcL() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::SetArchiveCrcL( RFile64& aArchive, TUint32 aCrc, TUint aOffset ) + { + TInt error = KErrNone; + + // Prepare externalized representation of crc + TBuf8< KMMCScArchiveCrcByteCount > crcData; + RDesWriteStream writeStream( crcData ); + CleanupClosePushL( writeStream ); + writeStream.WriteInt32L( aCrc ); + writeStream.CommitL(); + CleanupStack::PopAndDestroy( &writeStream ); + + // Then write crc to the file itself + error = aArchive.Write( static_cast( aOffset ), crcData ); + User::LeaveIfError( error ); + } + + +// --------------------------------------------------------------------------- +// MMCScBkupArchiveUtils::CalculateCrcFromArchive() +// +// +// --------------------------------------------------------------------------- +void MMCScBkupArchiveUtils::CalculateCrcFromArchive( TUint32& aCrc, RFile64& aArchive, TUint32 aOffset, TUint32 aLength ) + { + const TInt KBigBufSize=0x10000; + const TInt KMediumBufSize=0x8000; + const TInt KSmallBufSize=0x1000; + + // Allocate as large buffer as possible for crc validation, because + // need to read file content in chunks for crc calculation. + HBufC8* bufPtr = HBufC8::New(KBigBufSize); + + if ( bufPtr == NULL ) + bufPtr = HBufC8::New(KMediumBufSize); + if ( bufPtr == NULL ) + bufPtr = HBufC8::New(KSmallBufSize); + + if ( bufPtr != NULL) + { + TPtr8 copyBuf = bufPtr->Des(); + TInt64 pos = aOffset; + TInt size = aLength; + + // Loop through archive file skipping archive crc + while(size) + { + TInt s; + + s = Min( size, copyBuf.MaxSize() ); + + TInt error = aArchive.Read( pos, copyBuf, s ); + + if ( error == KErrNone && copyBuf.Length() != s ) + break; + + pos += s; + size -= s; + Mem::Crc32(aCrc, copyBuf.Ptr(), copyBuf.Length()); + } + + delete bufPtr; + } + } +#endif // RD_FILE_MANAGER_BACKUP +