diff -r 000000000000 -r 05e9090e2422 skins/AknSkins/srvsrc/aknssrvactivebackupdataclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/skins/AknSkins/srvsrc/aknssrvactivebackupdataclient.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,1192 @@ +/* +* Copyright (c) 2007-2008 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: Skin server's active data owner in backup/restore. +* +*/ + + +#include + +#include "aknssrvactivebackupdataclient.h" +#include "AknsSrvUtils.h" + +#include "AknsDebug.h" + +// Maximum size of header info. +const TUint KMaxHeaderSize = 256; + +// number of bytes to read from file per block +const TUint KCheckSumBlockSize = 128; + +// Default size of restore/backup stream size in bytes. +const TUint KArbitraryNumber=1024; + +// 8 bytes +const TUint K8Bytes = 8; +// 16 bytes +const TUint K16Bytes = 16; +// Length of extension (including preceding dot). +const TInt KExtensionLength = 4; + +_LIT( KSkinRootDir,":\\resource\\skins\\" ); + +// ======== MEMBER FUNCTIONS ======== + +// Skin files are backed up in the following format. +// filename contains drive and path in addition to filename. +// + +// --------------------------------------------------------------------------- +// Symbian constructor. +// --------------------------------------------------------------------------- +// +CAknsSrvActiveBackupDataClient* CAknsSrvActiveBackupDataClient::NewL( RFs& aFsSession ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::NewL" ); + CAknsSrvActiveBackupDataClient* self = + new( ELeave ) CAknsSrvActiveBackupDataClient( aFsSession ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CAknsSrvActiveBackupDataClient::~CAknsSrvActiveBackupDataClient() + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::destructor" ); + iFileArray.Reset(); + iFileArray.Close(); + iFile.Close(); + delete iBuffer; + } + +// --------------------------------------------------------------------------- +// Prepare for backup and restore ( no actions). +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::PrepareForBURL( TInt /*aBackupStateValue*/ ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::PrepareForBURL" ); + } + +// --------------------------------------------------------------------------- +// Inform that all data has been backed up or restored. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::AllSnapshotsSuppliedL() + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::AllSnapshotsSuppliedL" ); + // Finalize and cleanup. + return; + } + +// --------------------------------------------------------------------------- +// Not supported. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::ReceiveSnapshotDataL( + TDriveNumber /*aDrive*/, TDesC8& /*aBuffer*/, TBool /*aLastSection*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::ReceiveSnapshotDataL" ); + User::Leave( KErrNotSupported ); + } + +// --------------------------------------------------------------------------- +// Make a guess about data size. +// --------------------------------------------------------------------------- +// +TUint CAknsSrvActiveBackupDataClient::GetExpectedDataSize( + TDriveNumber /*aDrive*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetExpectedDataSize" ); + // we have no idea at this point - we even don't know what is to be + // backed up yet + return KArbitraryNumber; + } + +// --------------------------------------------------------------------------- +// Not supported. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::GetSnapshotDataL( + TDriveNumber /*aDrive*/, TPtr8& /*aBuffer*/, TBool& /*aFinished*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetSnapshotDataL" ); + User::Leave( KErrNotSupported ); + } + +// --------------------------------------------------------------------------- +// Initialize for backup - collect to-be-backed-up-files. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::InitialiseGetBackupDataL( + TDriveNumber aDrive) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseGetBackupDataL" ); + DoInitialiseGetBackupDataL( aDrive ); + } + +// --------------------------------------------------------------------------- +// Run state machine for backup. Each file is opened and streamed to the +// BUR engine. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::GetBackupDataSectionL( + TPtr8& aBuffer, TBool& aFinished) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL" ); + // Make sure that the buffer is empty and starts from the beginning + aBuffer.SetLength(0); + + // don't assume they set it to false + aFinished = EFalse; + // any files to backup + if( iFileArray.Count() == 0 ) + { + // nothing to backup - just return the finished flag + aFinished = ETrue; + // clear the list and stop. + iFileArray.Reset(); + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL no files" ); + return; + } + + // run the state machine + while( ETrue ) + { + switch( iBackupState ) + { + // open a file for processing + case EBackupNoFileOpen: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState ); + if( iFileIndex >= iFileArray.Count() ) + { + // all files have been processed - send the finished flag + aFinished = ETrue; + // clear the list and stop. + iFileArray.Reset(); + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL all processed" ); + return; + } + + // open file to send + TInt rc=iFile.Open( iFsSession, + iFileArray[iFileIndex].FullName(), + ( EFileRead | EFileShareExclusive | EFileStream ) ); + if( rc != KErrNone ) + { + // there's nothing we can do if we can't open the file + // so we just skip it + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL skip file" ); + ++iFileIndex; + break; + } + iBackupState = EBackupOpenNothingSent; + break; + } + // nothing sent (so far) for this file - send the header info + case EBackupOpenNothingSent: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState ); + TInt fileSize; + TInt retValue = iFile.Size( fileSize ); + if( retValue != KErrNone || fileSize == 0 ) + { + // empty or unreadable - skip this file + iBackupState = EBackupEndOfFile; + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL skip file2" ); + break; + } + + // build the header - this is an instance member because it + // has to persist over multiple calls to this method + TPtr headerPtr = iBuffer->Des(); + + // get the checksum - only grab last 4 bytes - enough to be satisfied that + // the backup and restore worked ok + TUint64 checksum = CheckSumL( iFile ) & 0xffffffff; + + // build the header - note NOT AppendFormat(); wipes out previous content. + // + headerPtr.Format(_L("%8x%8lx%8x%8x"), + iFileArray.Count(), + checksum, + fileSize, + iFileArray[iFileIndex].FullName().Length()); + headerPtr.Append( iFileArray[iFileIndex].FullName() ); + + // we need it to look like an 8bit buffer + TPtr8 headerPtr8( + (TUint8*)headerPtr.Ptr(), + headerPtr.Size(), + headerPtr.Size() ); + + // Check how much room is left in the buffer. + // it starts out empty when we get it from the BUE + TInt available = aBuffer.MaxSize() - aBuffer.Size(); + + // Check is there enough room for the whole header. + TBool enoughRoom = headerPtr8.Size() < available; + + // append the header to the buffer (only till it's full) + aBuffer.Append( + headerPtr8.Ptr(), + enoughRoom ? headerPtr8.Size() : available) ; + + // decide what needs to happen next + // if complete then we need data, otherwise we need to put + // the rest of the header in the next chunk + if( enoughRoom ) + { + iBackupState = EBackupOpenAllHeaderSent; + } + else + { + // we need to keep track of how much of the header has + // been sent so that we only send the reminder on the next + // iteration + iHeaderSent = available; + iBackupState = EBackupOpenPartHeaderSent; + } + + // if the buffer's full we need to return control to the backup engine + // Because the finishedFlag is not set, the BUE will process this + // chunk and then ask for another + if( aBuffer.Size() == aBuffer.MaxSize() ) + { + return; + } + break; + } + // need to send the rest of the header + case EBackupOpenPartHeaderSent: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState ); + // get back the header - this is already loaded with the necessary info + // from the previous state we were in + TPtr headerPtr = iBuffer->Des(); + + // we need it to look like an 8bit buffer + TPtr8 headerPtr8( + (TUint8*)headerPtr.Ptr(), + headerPtr.Size(), + headerPtr.Size() ); + + // Check how many bytes have we yet to send. + TInt bytesRemaining = headerPtr.Size() - iHeaderSent; + + // Check how much room in the buffer. + TInt available = aBuffer.MaxSize() - aBuffer.Size(); + + // enough, if not send as much as we can + TBool enoughRoom = bytesRemaining < available; + aBuffer.Append( + headerPtr8.Ptr() + iHeaderSent, + enoughRoom ? bytesRemaining : available ); + + if( enoughRoom ) + { + iHeaderSent = 0; // ready for next header + iBackupState = EBackupOpenAllHeaderSent; + } + else + { + iHeaderSent += available; // ready to do round again + // state remains as EBackupOpenPartHeaderSent + } + + // if the buffer's full we need to return control to the backup engine + // Because the finishedFlag is not set, the BUE will process this + // chunk and then ask for another + if( aBuffer.Size() == aBuffer.MaxSize() ) + { + return; + } + break; + } + // need to send some data + case EBackupOpenAllHeaderSent: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState ); + // how many bytes can we send + TInt available = aBuffer.MaxSize() - aBuffer.Size(); + + // create a buffer for this data (plus one for PtrZ) + HBufC8* transferBuffer = HBufC8::NewLC( available + 1 ); + TPtr8 bufferToSend = transferBuffer->Des(); + + // get the data + User::LeaveIfError( iFile.Read( bufferToSend, available ) ); + + // Check how much did we actually read. + TInt bytesRead = bufferToSend.Size(); + + // EOF + if( bytesRead == 0 ) + { + CleanupStack::PopAndDestroy( transferBuffer ); + iBackupState = EBackupEndOfFile; + break; + } + + // add it to the aBuffer + aBuffer.Append( bufferToSend.PtrZ(), bytesRead ); + + // tidy up + CleanupStack::PopAndDestroy( transferBuffer ); + + // if the buffer's full we need to return control to the backup engine + if( aBuffer.Size() == aBuffer.MaxSize() ) + { + return; + } + break; + } + // At the end of the current file. + case EBackupEndOfFile: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState ); + + // how many bytes can we send + if ( aBuffer.Size() != 0 ) + { + TInt available = aBuffer.MaxSize() - aBuffer.Size(); + // pad the end of the buffer with NULL. + HBufC8* transferBuffer = HBufC8::NewLC( available + 1 ); + TPtr8 bufferToSend = transferBuffer->Des(); + bufferToSend.FillZ(); + aBuffer.Append( bufferToSend.PtrZ(), available ); + CleanupStack::PopAndDestroy( transferBuffer ); + if( aBuffer.Size() != aBuffer.MaxSize() ) + { + // Sanity check + User::Leave( KErrGeneral ); + } + } + // Close file and move on to next file. + iFile.Close(); + ++iFileIndex; + // Start all over again. + iBackupState = EBackupNoFileOpen; + break; + } + default: + { + // not reachable + return; + } + } + } + } + +// --------------------------------------------------------------------------- +// Initialize restore. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::InitialiseRestoreBaseDataL( + TDriveNumber /*aDrive*/ ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseRestoreBaseDataL" ); + // this is the first state of the restore state machine + iRestoreState = ERestoreNumberOfFiles; + // to keep track in the state machine whether any data was actually sent + iDataRestored = EFalse; + iFilesRestored = 0; + } + +// --------------------------------------------------------------------------- +// Run state machine for restore. Receive stream from BUR engine and turn it +// to file(s). +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL( + TDesC8& aBuffer, TBool aFinished ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL" ); + // convert the buffer - this is KMaxHeaderSize=256 + TInt bufferIndex; + TPtr bufPtr = iBuffer->Des(); + + // used to walk the buffer + // got a new buffer - because each time this method is called, we have a + // fresh chunk of data + bufferIndex = 0; + + // to mark when the state machine is through + TBool done = EFalse; + + // check whether this is an empty restore + if( aFinished && !iDataRestored ) + { + // we have to do this and not rely on aFinishedFlag alone, because + // if aFinished is used, we'll process the last state of the machine + // which does tidyup, except that if there was no data, no tidyup should + // be done + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL empty restore" ); + return; + } + + // run the machine + do + { + // Check how many bytes are there available in the buffer for processing. + TInt bytesAvailable = aBuffer.Length() - bufferIndex; + // the reason why we are testing finishedFlag is because we must + // make sure we re-enter the machine to do the tidyup + if( bytesAvailable <= 0 && !aFinished ) + { + // ran out of data in the chunk + // so we return and wait for more data to arrive + return; + } + + if( aFinished && + iRestoreState != ERestoreComplete && + iRestoreState != ERestoreExpectMoreData ) + { + // ran out of data early + // will be ERestoreComplete if data not aligned on 128 + // will be ERestoreExpectMoreData if data aligned on 128 + User::Leave( KErrCorrupt ); + } + // yep there was some data in the chunk if we got here + if( bytesAvailable > 0 ) + { + iDataRestored = ETrue; + } + switch( iRestoreState ) + { + case ERestoreNumberOfFiles: // 16 bytes + { + TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // stick it in the heap buffer + bufPtr.Zero(); + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == K8Bytes ) + { + // If file size is now read, read file name size next. + iRestoreState = ERestoreExpectChecksum; + } + + break; + } + case ERestoreExpectChecksum: + { + // first of all, process the heap buffer to extract the checksum + TLex lex( bufPtr ); + lex.SkipSpace(); + lex.Val( iNumberofFiles, EHex ); + + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // if we have 16 bytes, get them; + // otherwise get what we have available. + // if not complete then we need to go around again to get the rest + TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable; + + // extract the bytes + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // stick it in the heap buffer + bufPtr.Zero(); + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == 8 ) + { + // If complete checksum is available, move on to filesize. + iRestoreState = ERestoreExpectFileSize; + } + else + { + // Otherwise continue reading the checksum. + iRestoreState = ERestoreExpectMoreChecksum; + } + break; + } + // checksum overran buffer on first/subsequent read. + case ERestoreExpectMoreChecksum: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // Check how many more bytes do we want. + TInt bytesNeeded=( K8Bytes - bufPtr.Length() ) << 1; + TInt bytesToGet= + bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable; + + // extract the bytes + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // append it to the heap buffer + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == K8Bytes ) + { + // If complete checksum is now available, move on to filesize. + iRestoreState = ERestoreExpectFileSize; + } + else + { + // same state : ERestoreExpectMoreChecksum; + } + break; + } + case ERestoreExpectFileSize: // 16 bytes + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // first of all, process the heap buffer to extract the checksum + TLex lex( bufPtr ); + lex.SkipSpace(); + lex.Val( iChecksum, EHex ); + + // now start getting the file size + TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // stick it in the heap buffer + bufPtr.Zero(); + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == K8Bytes ) + { + // If file size is now read, read file name size next. + iRestoreState = ERestoreExpectFileNameSize; + } + else + { + // Otherwise continue reading the file size. + iRestoreState = ERestoreExpectMoreFileSize; + } + break; + } + // file size didn't fit into one buffer + case ERestoreExpectMoreFileSize: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // Check how many more bytes do we want. + TInt bytesNeeded = ( K8Bytes - bufPtr.Length() ) << 1; + TInt bytesToGet = bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // append it to the heap buffer + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == K8Bytes ) + { + // If file size is now read, read file name size next. + iRestoreState = ERestoreExpectFileNameSize; + } + else + { + // same state ERestoreExpectMoreFileSize; + } + break; + } + // the size of the file name to restore + case ERestoreExpectFileNameSize: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // first of all, process the heap buffer to extract the file size + TLex lex( bufPtr ); + lex.SkipSpace(); + lex.Val( iFileSize, EHex ); + + // now start getting the file name size + TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // stick it in the heap buffer + bufPtr.Zero(); + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == K8Bytes ) + { + // If filename size is now read, read filename next. + iRestoreState = ERestoreExpectFileName; + } + else + { + // Otherwise, continue reading the filename size. + iRestoreState = ERestoreExpectMoreFileNameSize; + } + break; + } + // the file name size overran the buffer + case ERestoreExpectMoreFileNameSize: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // Check how many more bytes do we want. + TInt bytesNeeded = ( K8Bytes - bufPtr.Length() ) << 1; + TInt bytesToGet = bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // append it to the heap buffer + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == K8Bytes ) + { + // If filename size is now read, read filename next. + iRestoreState = ERestoreExpectFileName; + } + else + { + // same state ERestoreExpectMoreFileNameSize; + } + break; + } + case ERestoreExpectFileName: // the name of the file to restore + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // first of all, process the heap buffer to extract the file name size + TLex lex( bufPtr ); + lex.SkipSpace(); + lex.Val( iFileNameSize, EHex ); + + // now start getting the file name + TInt bytesToGet = bytesAvailable >= iFileNameSize << 1 ? iFileNameSize << 1:bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // stick it in the heap buffer + bufPtr.Zero(); + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == iFileNameSize ) + { + // If filename is now read, start reading the file content. + iRestoreState = ERestoreExpectData; + } + else + { + // Otherwise, continue reading the file. + iRestoreState = ERestoreExpectMoreFileName; + } + break; + } + // the file name overran the buffer + case ERestoreExpectMoreFileName: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // Check how many more bytes do we want. + TInt bytesNeeded = ( iFileNameSize -bufPtr.Length() ) << 1; + TInt bytesToGet = bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable; + TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet ); + bufferIndex += bytesToGet; + + // convert to 16 bit + TPtr ptr16( + (TUint16*) ptr8.Ptr(), + bytesToGet >> 1, + bytesToGet >> 1 ); + + // append it to the heap buffer + bufPtr.Append( ptr16 ); + + if( bufPtr.Length() == iFileNameSize ) + { + // If filename is now read, start reading the file content. + iRestoreState = ERestoreExpectData; + } + else + { + // same state ERestoreExpectMoreFileName; + } + break; + } + // now for the data + case ERestoreExpectData: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + iFileOpenError = EFalse; + // iFileSize counts down + TInt bytesToGet = bytesAvailable >= iFileSize ? iFileSize : bytesAvailable; + + if ( iFsSession.IsValidName( bufPtr ) && + !AknsSrvUtils::IsFile( iFsSession, bufPtr ) && + RestoreFileInPrivateDirectoryL( bufPtr ) == KErrNone ) + { + // write it + TInt fileErr = iFile.Write( aBuffer.Mid( bufferIndex, bytesToGet ) ); + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL file write %d", fileErr ); + } + else + { + iFileOpenError = ETrue; + } + + // update our counters + bufferIndex += bytesToGet; + iFileSize -= bytesToGet; + + // Check if finished now. + if( iFileSize == 0 ) + { + // If file is now written, restore is complete (for this file). + iRestoreState = ERestoreComplete; + } + else + { + // Otherwise, continue reading and writing the file. + iRestoreState = ERestoreExpectMoreData; + } + if ( iFileOpenError ) + { + return; + } + + break; + } + // will almost certainly exceed a single buffer + case ERestoreExpectMoreData: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // Check how much more. + TInt bytesToGet = bytesAvailable >= iFileSize ? iFileSize : bytesAvailable; + + // write it + if (!iFileOpenError) + { + TInt fileErr = iFile.Write( aBuffer.Mid( bufferIndex, bytesToGet ) ); + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL file write %d", fileErr ); + } + + // update the counters + bufferIndex += bytesToGet; + iFileSize -= bytesToGet; + + // Check if finished now. + if( iFileSize == 0 ) + { + // If file is now written, restore is complete (for this file). + iRestoreState = ERestoreComplete; + } + else + { + // same state ERestoreExpectMoreData; + } + break; + } + // file completely restored + case ERestoreComplete: + { + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState ); + // calculate the checksum + if(!iFileOpenError) + { + TUint64 cksum = CheckSumL( iFile ) & 0xffffffff; + + // validate that the checksum matches + if( cksum != iChecksum ) + { + AKNS_TRACE_DEBUG2("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL checksum fail %d %d", cksum, iChecksum ); + User::Leave( KErrCorrupt ); + } + + // Done with the file, so close it. + iFile.Close(); + } + iFilesRestored++; + + // end of data - Check if another file is to be restored. + iRestoreState = ERestoreNumberOfFiles; + iFileOpenError = EFalse; + + // Each file should end at the end of buffer. + aFinished = ETrue; + return; + } + default: + break; + } + } while(!done); + } + +// --------------------------------------------------------------------------- +// Incremental restoration is not supported. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::InitialiseRestoreIncrementDataL( + TDriveNumber /*aDrive*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseRestoreIncrementDataL" ); + User::Leave( KErrNotSupported ); + } + +// --------------------------------------------------------------------------- +// Incremental restoration is not supported. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::RestoreIncrementDataSectionL( + TDesC8& /*aBuffer*/, TBool /*aFinished*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreIncrementDataSectionL" ); + User::Leave( KErrNotSupported ); + } + +// --------------------------------------------------------------------------- +// Called when restore is complete - sets data back to initial state. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::RestoreComplete(TDriveNumber /*aDrive*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreComplete" ); + // Possibly delete some extra data. + iDataRestored = EFalse; + iRestoreState = ERestoreNumberOfFiles; + } + +// --------------------------------------------------------------------------- +// Tidy up when operation is over. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::TerminateMultiStageOperation() + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::TerminateMultiStageOperation" ); + iFileArray.Reset(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TUint CAknsSrvActiveBackupDataClient::GetDataChecksum(TDriveNumber /*aDrive*/) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetDataChecksum" ); + // not required - not implemented + return KArbitraryNumber; + } + +// --------------------------------------------------------------------------- +// Initialize backup. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::InitialiseGetProxyBackupDataL( + TSecureId /*aSID*/, TDriveNumber aDrive ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseGetProxyBackupDataL" ); + DoInitialiseGetBackupDataL( aDrive ); + } + +// --------------------------------------------------------------------------- +// Initializes restore state machine. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::InitialiseRestoreProxyBaseDataL( + TSecureId /*aSID*/, TDriveNumber /*aDrive*/ ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseRestoreProxyBaseDataL" ); + // this is the first state of the restore state machine + iRestoreState = ERestoreNumberOfFiles; + // to keep track in the state machine whether any data was actually sent + iDataRestored = EFalse; + } + +// --------------------------------------------------------------------------- +// Creates a checksum for the files. +// --------------------------------------------------------------------------- +// +TUint64 CAknsSrvActiveBackupDataClient::CheckSumL(const RFile& aOpenFile) const + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::CheckSumL" ); + // scoot through the database file building the checksum + TInt seekPos = 0; // rewind first + User::LeaveIfError( aOpenFile.Seek( ESeekStart, seekPos ) ); + TUint64 total = 0; + HBufC8* block = HBufC8::NewL( KCheckSumBlockSize ); + CleanupStack::PushL( block ); + TPtr8 ptr=block->Des(); + while( ETrue ) + { + User::LeaveIfError( aOpenFile.Read( ptr ) ); + TInt len = ptr.Length(); + if( len == 0 ) + { + break; + } + // calculate the checksum + for( TInt i = 0; i < len; ++i ) + { + TUint64 carry = total&(0x8000000000000000ULL); + total<<=1; + if( carry ) + { + total|=1; + } + TUint in = ptr[i]; + total += in; + } + }; + CleanupStack::PopAndDestroy( block ); + // restore file position + seekPos = 0; + User::LeaveIfError( aOpenFile.Seek( ESeekStart, seekPos ) ); + return total; + } + +// --------------------------------------------------------------------------- +// Scan directory for files. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::ScanDirectoryForSkinFilesL( + const TDesC& aRootDir ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::ScanDirectoryForSkinFilesL" ); + CDirScan *dirScan = CDirScan::NewLC( iFsSession ); + dirScan->SetScanDataL( + aRootDir, + KEntryAttNormal | KEntryAttHidden | KEntryAttSystem | + KEntryAttDir, + ESortNone ); + + // Fetch all directories and files from root. + CDir* entryList = NULL; + TParse parse; + for(;;) + { + TRAPD( err, dirScan->NextL( entryList ) ); + + // Stop in error case, or if no more data. + if (!entryList || ( err != KErrNone) ) + { + break; + } + + for (TInt i=0; i < entryList->Count(); i++) + { + TEntry entry = (*entryList)[i]; + const TDesC& dir = dirScan->FullPath(); + parse.Set( entry.iName, &dir, NULL ); + if ( !entry.IsDir() ) + { + iFileArray.Append( parse ); + } + } + delete entryList; + } + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::ScanDirectoryForSkinFilesL noFiles=%d", iFileArray.Count() ); + + // Destroy the list. + CleanupStack::PopAndDestroy( dirScan ); + } + +// --------------------------------------------------------------------------- +// Re-creates backed-up file in private directory. +// --------------------------------------------------------------------------- +// +TInt CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL( + const TDesC& aFileName ) + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL" ); + _LIT( KAknsStaticPath, "\\private\\10207114\\import" ); + _LIT( KAknsSknExtension, ".SKN" ); + TBool parseError = EFalse; + TInt fileErr = KErrNone; + + HBufC* fileNameBuffer = HBufC::NewL( KMaxFileName ); + TParsePtrC fileName( aFileName ); + TPtr bufferPtr = fileNameBuffer->Des(); + + // First append drive and static path. + if ( fileName.DrivePresent() ) + { + bufferPtr.Append( fileName.Drive() ); + } + else + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse error1" ); + parseError = ETrue; + } + if ( !parseError ) + { + bufferPtr.Append( KAknsStaticPath ); + } + + if ( fileName.PathPresent() && !parseError ) + { + // Take path without the trailing backslash. + TPtrC path = fileName.Path().Left( fileName.Path().Length() - 1 ); + + // Locate last backslash. + TChar backslash('\\'); + TInt bsLoc = path.LocateReverse( backslash ); + + // Append skin PID to the directory. + bufferPtr.Append( fileName.Path().Mid( bsLoc ) ); + + if ( fileName.ExtPresent() ) + { + // Last, append filename. Now string is complete. + bufferPtr.Append( fileName.NameAndExt() ); + + // switch the extension and check for file existance. + bufferPtr.Replace( + bufferPtr.Length() - KExtensionLength, + KExtensionLength, + KAknsSknExtension ); + if ( !AknsSrvUtils::IsFile( iFsSession, bufferPtr ) ) + { + // There is no matching .skn-file, do not restore the graphics file. + fileErr = KErrNotFound; + } + + // switch back the graphics file extension. + bufferPtr.Replace( + bufferPtr.Length() - KExtensionLength, + KExtensionLength, + fileName.Ext() ); + } + else + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse error2" ); + parseError = ETrue; + } + } + else + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse error3" ); + parseError = ETrue; + } + + if( !parseError && fileErr == KErrNone ) + { + if ( AknsSrvUtils::IsFile( iFsSession, bufferPtr ) ) + { + // Do not restore, if the file already exists. + fileErr = KErrAlreadyExists; + } + else + { + // Create the file. + fileErr = iFile.Replace( + iFsSession, + bufferPtr, + ( EFileWrite | EFileShareExclusive | EFileStream ) ); + } + } + + AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse ret=%d", fileErr ); + if ( fileErr != KErrNone ) + { + // If error creating or parsing the file, skip to next one. + return fileErr; + } + if ( parseError ) + { + return KErrArgument; + } + return KErrNone; + } + +// --------------------------------------------------------------------------- +// C++ constructor. +// --------------------------------------------------------------------------- +// +CAknsSrvActiveBackupDataClient::CAknsSrvActiveBackupDataClient( + RFs& aFsSession ) : iFsSession( aFsSession ) + { + } + +// --------------------------------------------------------------------------- +// 2nd phase constructor. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::ConstructL() + { + AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::ConstructL" ); + iBuffer=HBufC::NewL( KMaxHeaderSize ); + } + +// --------------------------------------------------------------------------- +// Do initialise get backup data. +// --------------------------------------------------------------------------- +// +void CAknsSrvActiveBackupDataClient::DoInitialiseGetBackupDataL( + TDriveNumber aDrive ) + { + // this is the index of the file being processed - point to the beginning + iFileIndex=0; + // the first state of the backup state machine + iBackupState=EBackupNoFileOpen; + + TFileName path; + TChar driveLetter; + RFs::DriveToChar( aDrive, driveLetter ); + path.Append( driveLetter ); + path.Append( KSkinRootDir ); + // Store the directories and filenames. + ScanDirectoryForSkinFilesL( path ); + } + +// End of file