diff -r 000000000000 -r d0791faffa3f backupandrestore/backupengine/src/sbebufferhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backupandrestore/backupengine/src/sbebufferhandler.cpp Tue Feb 02 01:11:40 2010 +0200 @@ -0,0 +1,1198 @@ +// 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 "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: +// Implementation of CBufferFileWriter and CBufferReader +// +// + +/** + @file +*/ + + +#include "sbebufferhandler.h" +#include "sblog.h" +#include + +namespace conn + { + template + TBool ReadFromBufferF(T& aT, TUint8*& appCurrent, const TUint8* apEnd) + /** Template class to read flat structures from the buffer + + @param aT on return the flat structure. + @param appCurrent The current point into the buffer. + @param apEnd The end of the buffer. + @return ETrue if read succesfully. EFalse if a retry is needed. + */ + { + static TBuf8 SBuffer; // Static buffer used for buffering! + TBool ret = EFalse; + + // Is there anything already in the buffer? + TUint8* ptr = NULL; + if (SBuffer.Size() > 0) + { + TInt size = SBuffer.Size(); + SBuffer.Append(appCurrent, sizeof(T) - size); + ptr = const_cast(SBuffer.Ptr()); + + appCurrent += sizeof(T) - size; + + ret = ETrue; + } // if + else + { + // Is there enough room in current + if ((apEnd - appCurrent) < static_cast(sizeof(T))) + { + // Need to buffer + SBuffer.Copy(appCurrent, apEnd - appCurrent); + } // if + else + { + ptr = appCurrent; + appCurrent += sizeof(T); + ret = ETrue; + } // else + } // else + + if (ret) + { + // Use a loop to copy to avoid alignment issues + TUint8* ptrOut = reinterpret_cast(&aT); + for (TUint x = 0; x < sizeof(T); x++) + { + *ptrOut++ = *ptr++; + } // for + + SBuffer.SetLength(0); + } + + return ret; + } + + template TBool ReadFromBufferF(TFileFixedHeader&, TUint8*&, const TUint8*); + template TBool ReadFromBufferF(TSnapshot&, TUint8*&, const TUint8*); + + template + TBool WriteToBufferF(T& aT, TPtr8& aPtr) + /** Writes flat structures to the buffer. + + NOTE: This should _ONLY_ be used to write T classes to the buffer. + + @param aT The flat structure to write to the buffer. + @param ptr The buffer to write to. + @return ETrue on success. EFalse on failure. + */ + { + TBool ret = EFalse; + + if ((aPtr.MaxSize() - aPtr.Size()) >= static_cast(sizeof(T))) + { + aPtr.Append(reinterpret_cast(&aT), sizeof(T)); + ret = ETrue; + } // if + + return ret; + } + + TBool ReadFromBufferV(TPtr8& aT, TInt aSize, TUint8*& appCurrent, const TUint8* apEnd) + /** Reads from the buffer. + + @param aT on return the data read. + @param aSize size of the data to read. + @param appCurrent Pointer to read from. + @param apEnd the end of the data. + @return ETrue on success. EFalse on failure. + */ + { + TBool ret = EFalse; + + // Does into already contain data? + if (aT.Size() > 0) + { + TInt tocopy = aSize - aT.Size(); + aT.Append(appCurrent, tocopy); + appCurrent += tocopy; + ret = ETrue; + } // if + else + { + // Is there enough data? + if ((apEnd - appCurrent) < aSize) + { + aT.Copy(appCurrent, apEnd - appCurrent); + appCurrent = const_cast(apEnd); + } // if + else + { + aT.Copy(appCurrent, aSize); + appCurrent += aSize; + ret = ETrue; + } // else + } // else + + return ret; + } + + TBool WriteToBufferV(const TPtr8& aPtr, TInt aSize, TPtr8& aBuffer) + /** Writes some vairable data to the buffer. + + NOTE: This should _ONLY_ be used to write T classes to the buffer. + + @param aPtr buffer to read from. + @param aSize size of the data to write. + @param aBuffer the buffer to write to. + @return ETrue on success. EFalse on failure. + */ + { + TBool ret = EFalse; + + if ((aBuffer.MaxSize() - aBuffer.Size()) >= aSize) + { + aBuffer.Append(aPtr.Ptr(), aSize); + ret = ETrue; + } // if + + + return ret; + } + + CBufferFileWriter* CBufferFileWriter::NewL(RFs& aFs, CDesCArray* aFileNames) + /** Symbain constructor + + @param aFs Handle to the Symbian Fs file server + @param aFileNames list of files to write ownership transfer + @return a CBufferFileWriter. + */ + { + CBufferFileWriter* self = new(ELeave) CBufferFileWriter(aFs, aFileNames); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } // NewL + + CBufferFileWriter::CBufferFileWriter(RFs& aFs, CDesCArray* aFileNames) : + iFs(aFs), iFileNames(aFileNames) + /** Standard C++ constructor + + @param aFs an RFS to use in this class. + */ + { + } // CBufferFileWriter + + CBufferFileWriter::~CBufferFileWriter() + /** Standard C++ destructor + */ + { + delete iFileNames; + iFileHandle.Close(); + } + + void CBufferFileWriter::ConstructL() + /** Symbain second phase constructor + + @param aFileNames list of files to write + */ + { + #if defined(SBE_LOGGING_ENABLED) + if (iFileNames) + { + TUint count = iFileNames->Count(); + while(count--) + { + const TDesC& fileName = (*iFileNames)[count]; + __LOG2("CBufferFileWriter::ConstructL() - file[%04d] is: %S", count, &fileName); + } + } + + #endif + } + + void CBufferFileWriter::StartL(TPtr8& aBuffer, TBool& aCompleted) + /** Start writing the files to the buffer + + @param aBuffer The buffer to write to. + @param aCompleted on return if we have finished. + */ + { + __LOG("CBufferFileWriter::StartL() - START"); + WriteToBufferL(aBuffer, aCompleted); + __LOG("CBufferFileWriter::StartL() - END"); + } // StartL + + void CBufferFileWriter::ContinueL(TPtr8& aBuffer, TBool& aCompleted) + /** Continue writing the files to the buffer + + @param aBuffer The buffer to write to. + @param aCompleted on return if we have finished. + */ + { + __LOG("CBufferFileWriter::ContinueL() - START"); + WriteToBufferL(aBuffer, aCompleted); + __LOG("CBufferFileWriter::ContinueL() - END"); + } + + void CBufferFileWriter::WriteToBufferL(TPtr8& aBuffer, TBool& aCompleted) + /** Writes files to the buffer + + @param aBuffer The buffer to write to. + @param aCompleted on return if we have finished. + */ + { + aCompleted = EFalse; + + const TUint count = iFileNames->Count(); + while (iCurrentFile < count) + { + const TDesC& name = (*iFileNames)[iCurrentFile]; + + _LIT( KTrailingBackSlash, "\\" ); + if (name.Right(1) == KTrailingBackSlash() ) + { + // Directory entry + __LOG1("CBufferFileWriter::WriteToBufferL() - empty directory: %S ", &name); + if(!iHeaderWritten) + { + TFileFixedHeader header(name.Length(), 0, 0, 0); + if (WriteToBufferF(header, aBuffer) == EFalse) + { + __LOG("CBufferFileReader::WriteToBufferL() - WriteToBufferF() returned False so breaking!"); + break; + } + iHeaderWritten = ETrue; + } // if + + TPtr8 ptr(reinterpret_cast(const_cast(name.Ptr())), name.Size(), name.Size()); + + if (WriteToBufferV(ptr, ptr.Size(), aBuffer) == EFalse) + { + __LOG("CBufferFileReader::WriteToBufferL() - WriteToBufferV() returned False so breaking!"); + break; + } + + iHeaderWritten = EFalse; + iFileNameWritten = EFalse; + } + else + { + if (!iFileOpen) // File needs to be opened + { + __LOG1("CBufferFileWriter::WriteToBufferL() - trying to open: %S for reading", &name); + const TInt error = iFileHandle.Open(iFs, name, EFileRead | EFileShareReadersOnly); + if (error != KErrNone) + { + __LOG2("CBufferFileWriter::WriteToBufferL() - opening: %S for reading failed with error: %d", &name, error); + User::Leave(error); + } + + iFileOpen = ETrue; + } // if + + if (iFileOpen && !iHeaderWritten) + { + // File size + TInt size; + TInt err = iFileHandle.Size(size); + __LOG2("CBufferFileWriter::WriteToBufferL() - size of file is: %d (err: %d)", size, err); + TUint att; + err = iFileHandle.Att(att); + __LOG2("CBufferFileWriter::WriteToBufferL() - attributes: %d (err: %d)", size, err); + TTime modified; + err = iFileHandle.Modified(modified); + __LOG2("CBufferFileWriter::WriteToBufferL() - modified: %d (err: %d)", size, err); + TFileFixedHeader header((*iFileNames)[iCurrentFile].Length(), size, att, modified.Int64()); + if (WriteToBufferF(header, aBuffer) == EFalse) + { + __LOG("CBufferFileReader::WriteToBufferL() - WriteToBufferF() returned False so breaking!"); + break; + } + + iHeaderWritten = ETrue; + } // if + + // Write filename + if (!iFileNameWritten) + { + + TPtr8 ptr(reinterpret_cast(const_cast(name.Ptr())), name.Size(), name.Size()); + + if (WriteToBufferV(ptr, ptr.Size(), aBuffer) == EFalse) + { + __LOG("CBufferFileReader::WriteToBufferV() - WriteToBufferF() returned False so breaking!"); + break; + } + iFileNameWritten = ETrue; + } + + __LOG1("CBufferFileWriter::WriteToBufferL() - buffer is of length: %d", aBuffer.Length()); + + TInt bufferLeft = aBuffer.MaxSize() - aBuffer.Size(); + TPtr8 ptr(const_cast(aBuffer.Ptr()) + aBuffer.Size(), bufferLeft); + TInt fileSize = 0; + iFileHandle.Size(fileSize); + TInt fileLeft = fileSize - iOffset; + if (bufferLeft < fileLeft) + { + __LOG("CBufferFileWriter::WriteToBufferL() - buffer space available is less than file size!"); + + // Write buffer size + User::LeaveIfError(iFileHandle.Read(iOffset, ptr, bufferLeft)); // TODO: Is this correct? + aBuffer.SetLength(aBuffer.Length() + bufferLeft); + iOffset += bufferLeft; + break; + } // if + else + { + __LOG("CBufferFileWriter::WriteToBufferL() - enough space in buffer for whole file..."); + + // Write file size + User::LeaveIfError(iFileHandle.Read(ptr, fileLeft)); // TODO: Is this correct? + aBuffer.SetLength(aBuffer.Length() + fileLeft); + } // else + + __LOG1("CBufferFileWriter::WriteToBufferL() - After read from file, buffer is now of length: %d", aBuffer.Length()); + + iFileHandle.Close(); + iFileOpen = EFalse; + iHeaderWritten = EFalse; + iFileNameWritten = EFalse; + iOffset = 0; + } //else + ++iCurrentFile; + } // while + + if (iCurrentFile >= count) + { + aCompleted = ETrue; + } // if + } // WriteToBufferL + + CBufferFileReader* CBufferFileReader::NewL(RFs& aFs, RSnapshots* apSnapshots, MValidationHandler* aValidationHandler) + /** Symbian OS constructor + + @param aFs File server to use. + @param apSnapshots list of snapshots. + */ + { + __LOG("CBufferFileReader::NewL() - START"); + CBufferFileReader* self = new(ELeave) CBufferFileReader(aFs, apSnapshots, aValidationHandler); + + CleanupStack::PushL( self ); + + #ifdef SBE_LOGGING_ENABLED + if (apSnapshots) + { + const TInt count = apSnapshots->Count(); + __LOG1("CBufferFileReader::NewL() - Got %d snapshots to compare against during restore...", count); + + for(TInt x = 0; x < count; ++x) + { + const TDesC& snapshot = (*apSnapshots)[x]->FileName(); + __LOG3("CBufferFileReader::NewL() - snapshot[%4d/%4d] is: %S", x+1, count, &snapshot); + } // for x + + } + #endif + + __LOG("CBufferFileReader::NewL() - END"); + + CleanupStack::Pop( self ); + return self; + } // NewL + + CBufferFileReader::CBufferFileReader(RFs& aFs, RSnapshots* apSnapshots, MValidationHandler* aValidationHandler) : + iFs(aFs), iSnapshots(apSnapshots), iValidationHandler(aValidationHandler) + /** C++ constructor + + @param aFs File server to use. + @param apSnapshots list of snapshots. + */ + { + } // CBufferFileReader + + void CBufferFileReader::StartL(const TDesC8& aBuffer, TBool aLastSection) + /** Start reading from the buffer. + + @param aBuffer The buffer to read from. + @param aLastSection Is this the last section? + */ + { + __LOG("CBufferFileReader::StartL() - START"); + if (iSnapshots) + { + iSnapshots->Sort(CSnapshot::Compare); + } + ReadFromBufferL(aBuffer, aLastSection); + __LOG("CBufferFileReader::StartL() - END"); + } // StartL + + void CBufferFileReader::ContinueL(const TDesC8& aBuffer, TBool aLastSection) + /** Continue reading from the buffer. + + @param aBuffer The buffer to read from. + @param aLastSection Is this the last section? + */ + { + __LOG("CBufferFileReader::ContinueL() - START"); + ReadFromBufferL(aBuffer, aLastSection); + __LOG("CBufferFileReader::ContinueL() - END"); + } // ContinueL + + void CBufferFileReader::CheckFileInSnapshotL() + /** + Checks to see if a given file is in a snapshot. + */ + { + __LOG2("CBufferFileReader::CheckFileInSnapshot() - START - ipSnapshots: 0x%08x, iSnapshotChecked: %d", iSnapshots, iSnapshotChecked); + + iRestore = ETrue; + + if (iSnapshots) + { + CSnapshot* snapshot = CSnapshot::NewLC(TTime().Int64(), iFileName); + TInt res = iSnapshots->Find(snapshot, CSnapshot::Match); + if (res == KErrNotFound) + { + iRestore = EFalse; + } + CleanupStack::PopAndDestroy(snapshot); + } // if + + iSnapshotChecked = ETrue; + + __LOG2("CBufferFileReader::CheckFileInSnapshot() - END - iSnapshotChecked: %d, iRestore: %d", iSnapshotChecked, iRestore); + } + + void CBufferFileReader::RecreateDirL() + /** + Recreates a directory path on disk. + */ + { + __LOG1("CBufferFileReader::RecreateDirL() - START - iFileName: %S", &iFileName); + // Create the path + TInt err = iFs.MkDirAll(iFileName); + if ((err != KErrNone) && (err != KErrAlreadyExists)) + { + __LOG1("CBufferFileReader::WriteToFile() - making directory resulted in fatal error: %d", err); + User::Leave(err); + } // if + + __LOG("CBufferFileReader::RecreateDirL() - END"); + } + + + void CBufferFileReader::RecreateFileL() + /** + Recreates a file on disk. Deletes the original if it still exists. + */ + { + __LOG1("CBufferFileReader::RecreateFileL() - START - iFileName: %S", &iFileName); + // Create the path + TInt err = iFs.MkDirAll(iFileName); + if ((err != KErrNone) && (err != KErrAlreadyExists)) + { + __LOG1("CBufferFileReader::WriteToFile() - making directory resulted in fatal error: %d", err); + User::Leave(err); + } // if + + + err = iFileHandle.Replace(iFs, iFileName, EFileWrite); + __LOG1("CBufferFileReader::WriteToFile() - replacing file returned err: %d", err); + User::LeaveIfError( err ); + + iFileOpen = ETrue; + __LOG("CBufferFileReader::RecreateFileL() - END"); + } + + + TBool CBufferFileReader::WriteToFileL(TUint8*& aCurrent, const TUint8* aEnd) + /** + Writes data to a file. + + @param aCurrent start point of data to write. + @param aEnd end point of data to write. + @return ETrue if write finished. EFalse if there is more data to write. + */ + { + __LOG2("CBufferFileReader::WriteToFile() - START - iFileHandle: 0x%08x, iFixedHeader.iFileSize: %d", iFileHandle.SubSessionHandle(), iFixedHeader.iFileSize); + TBool retVal = ETrue; + TInt filesize; + const TInt err1 = iFileHandle.Size(filesize); + __LOG2("CBufferFileReader::WriteToFile() - fileSize: %d (err: %d)", filesize, err1); + User::LeaveIfError(err1); + if ((aEnd - aCurrent) >= (iFixedHeader.iFileSize - filesize)) + { + TPtr8 ptr(aCurrent, iFixedHeader.iFileSize -filesize, iFixedHeader.iFileSize - filesize); + const TInt err2 = iFileHandle.Write(ptr); + __LOG2("CBufferFileReader::WriteToFile() - writing %d bytes returned error: %d", ptr.Length(), err2); + User::LeaveIfError(err2); + + // Write the attributes & modified time + const TInt err3 = iFileHandle.Set(iFixedHeader.iModified, + iFixedHeader.iAttributes, KEntryAttNormal); + + __LOG1("CBufferFileReader::WriteToFile() - setting attribs returned error: %d", err3); + User::LeaveIfError(err3); + + // Move current along + aCurrent += iFixedHeader.iFileSize - filesize; + + // Finished reset state + Reset(); + } // if + else + { + TInt size = aEnd - aCurrent; + TPtr8 ptr(aCurrent, size, size); + const TInt err2 = iFileHandle.Write(ptr); + __LOG2("CBufferFileReader::WriteToFile() - writing %d bytes returned error: %d", ptr.Length(), err2); + + retVal = EFalse; + } // else + + __LOG1("CBufferFileReader::WriteToFile() - END - finished: %d", retVal); + return retVal; + } + + void CBufferFileReader::ReadFromBufferL(const TDesC8& aBuffer, TBool aLastSection) + /** Reads from the buffer and writes files to disk. + + @param aBuffer The buffer to read from. + @param aLastSection Is this the last section? + @leave KErrUnderflow More data is needed. + */ + { + __LOG5("CBufferFileReader::ReadFromBufferL() - START - iFileNameRead: %d, iSnapshotChecked: %d, iRestore: %d, iFileOpen: %d, iFileName: %S", iFileNameRead, iSnapshotChecked, iRestore, iFileOpen, &iFileName); + + TUint8* current = const_cast(aBuffer.Ptr()); + const TUint8* end = current + aBuffer.Size(); + + // Workaround for "dual fixed header in backup" error. Tries to detect the special error case where iFixedHeaderRead=true but filename wasn't read + if(iFixedHeaderRead && !iFileNameRead && !iBytesRead && (end-current) >= 12) + { + // Check the first 12 bytes of the header we already got (the iModified is different between the problematic second header) + const TUint8* tempbuf = (TUint8*)&iFixedHeader; + TBool workAroundNeeded = ETrue; + for(TInt i = 0; i < 12; i++) + { + if(current[i] != tempbuf[i]) + { + workAroundNeeded = EFalse; + break; + } + } + + if(workAroundNeeded) + { + __LOG("CBufferFileReader::ReadFromBufferL() - Dual header was detected, workaround!!!"); + iFixedHeaderRead = EFalse; // Mark that the processing loop reads the fixed header again + } + } + + while (current < end) + { + __LOG2("CBufferFileReader::ReadFromBufferL() - iFixedHeaderRead: %d, iLeftToSkip: %d", iFixedHeaderRead, iLeftToSkip); + + // Do we have the fixed header? + if (!iFixedHeaderRead) + { + if (ReadFromBufferF(iFixedHeader, current, end) == EFalse) + { + __LOG("CBufferFileReader::ReadFromBufferL() - ReadFromBufferF() returned False so breaking!"); + break; + } // if + + __LOG1("CBufferFileReader::ReadFromBufferL() - fixed header - iFileNameLength: %d", iFixedHeader.iFileNameLength); + __LOG1("CBufferFileReader::ReadFromBufferL() - fixed header - iFileSize: %d", iFixedHeader.iFileSize); + __LOG1("CBufferFileReader::ReadFromBufferL() - fixed header - iAttributes: %d", iFixedHeader.iAttributes); + + if ((iFixedHeader.iFileNameLength > KMaxFileName) || (!iFixedHeader.iFileNameLength)) + { + __LOG1("CBufferFileReader::ReadFromBufferL() - Leaving - iFileNameLength: %d more then MaxLength", iFixedHeader.iFileNameLength); + User::Leave(KErrOverflow); + } + + iFixedHeaderRead = ETrue; + } // if + + + __LOG1("CBufferFileReader::ReadFromBufferL() - iFileNameRead: %d", iFileNameRead); + if (!iFileNameRead) + { + TPtr8 ptr(reinterpret_cast(const_cast(iFileName.Ptr())), iBytesRead, iFixedHeader.iFileNameLength * KCharWidthInBytes); + + if (ReadFromBufferV(ptr, iFixedHeader.iFileNameLength * KCharWidthInBytes, current, end) == EFalse) + { + iBytesRead = ptr.Size(); + __LOG1("CBufferFileReader::ReadFromBufferL() - ReadFromBufferV() returned False - Filename bytes read: %d", iBytesRead); + break; + } // if + + iFileName.SetLength(iFixedHeader.iFileNameLength); + iFileNameRead = ETrue; + __LOG1("CBufferFileReader::ReadFromBufferL() - Got filename: %S", &iFileName); + } + + // Is the file in the snapshot, if not it was deleted in an increment and does not need restoring + __LOG1("CBufferFileReader::ReadFromBufferL() - iSnapshotChecked: %d", iSnapshotChecked); + if (!iSnapshotChecked) + { + CheckFileInSnapshotL(); + } // if + + __LOG2("CBufferFileReader::ReadFromBufferL() - iValidationHandler: 0x%08x, iRestore: %d", iValidationHandler, iRestore); + if (iValidationHandler != NULL) + { + if (iRestore) + { + iRestore = iValidationHandler->ValidFileL(iFileName); + __LOG1("CBufferFileReader::ReadFromBufferL() - validation handler result: %d", iRestore); + } + } + + if (!iRestore && !iLeftToSkip) + { + __LOG1("CBufferFileReader::ReadFromBufferL() - restore not permitted, skipping file data (%d bytes)", iFixedHeader.iFileSize); + iLeftToSkip = iFixedHeader.iFileSize; // So we can skip the bytes + } + + __LOG1("CBufferFileReader::ReadFromBufferL() - iFileOpen: %d", iFileOpen); + if (iRestore) + { + // Check if it is a directory or file + _LIT( KTrailingBackSlash, "\\" ); + if (iFileName.Right(1) == KTrailingBackSlash()) + { + __LOG("CBufferFileReader::ReadFromBufferL() - Attempting to recreate directory path..."); + RecreateDirL(); + Reset(); + } + else + { + // Have we opened the file? + if (!iFileOpen) + { + __LOG("CBufferFileReader::ReadFromBufferL() - Attempting to recreate file..."); + RecreateFileL(); + } + + // Write to the file + __LOG("CBufferFileReader::ReadFromBufferL() - Attempting to write to file..."); + if (!WriteToFileL(current, end)) + { + __LOG("CBufferFileReader::ReadFromBufferL() - WriteToFileL() returned False so breaking!"); + break; + } + }//if + } // if + else + { + // We need to skip the bytes in the data + __LOG2("CBufferFileReader::ReadFromBufferL() - We\'re in skip mode. EndPos: %8d, CurrentPos: %8d", end, current); + if ((end - current) >= iLeftToSkip) + { + current += iLeftToSkip; + + // Finished reset state + __LOG("CBufferFileReader::ReadFromBufferL() - Finished skipping"); + Reset(); + } // if + else + { + __LOG1("CBufferFileReader::ReadFromBufferL() - Still more data to skip...: %d bytes", iLeftToSkip); + iLeftToSkip = iLeftToSkip - (end - current); + break; + } // else + } // else + } // while + + __LOG3("CBufferFileReader::ReadFromBufferL() - aLastSection: %d, iFileOpen: %d, iLeftToSkip: %d", aLastSection, iFileOpen, iLeftToSkip); + + if ((aLastSection && iFileOpen) || + (aLastSection && (iLeftToSkip > 0))) + { + __LOG("CBufferFileReader::ReadFromBufferL() - Leaving with KErrUnderflow because not all skipped data was consumed!"); + User::Leave(KErrUnderflow); + } // if + + __LOG("CBufferFileReader::ReadFromBufferL() - END"); + } // ReadFromBufferL + + void CBufferFileReader::RedirectMIDletRestorePathL(const TDesC& aOriginal, CDesCArray& aRedirected) + /** Redirects the midlet restore path + + @param aOriginal the original path + @param aRedirected the redirected path + */ + { + TFileName redirectedFilename(KMIDletTempRestorePath); + // Backslash used to isolate the filename from aOriginal's absolute path + const TChar KTCharBackslash('\\'); + + // Isolate the filename from aOriginal and Append it to our temp path + redirectedFilename.Append(aOriginal.Mid(aOriginal.LocateReverseF(KTCharBackslash) + 1)); + aRedirected.AppendL(redirectedFilename); + } + + void CBufferFileReader::ReadMIDletsFromBufferL(const TDesC8& aBuffer, TBool aLastSection, + CDesCArray& aUnpackedFileNames) + /** Reads from the buffer and writes files to disk. + + @param aBuffer The buffer to read from. + @param aLastSection Is this the last section? + @leave KErrUnderflow More data is needed. + */ + { + TUint8* current = const_cast(aBuffer.Ptr()); + const TUint8* end = current + aBuffer.Size(); + TInt fileIndex = 0; + while (current < end) + { + // Do we have the fixed header? + if (!iFixedHeaderRead) + { + if (ReadFromBufferF(iFixedHeader, current, end) == EFalse) + { + __LOG("CBufferFileReader::ReadMIDletsFromBufferL() - ReadFromBufferF() returned False so breaking!"); + break; + } // if + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - fixed header - iFileNameLength: %d", iFixedHeader.iFileNameLength); + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - fixed header - iFileSize: %d", iFixedHeader.iFileSize); + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - fixed header - iAttributes: %d", iFixedHeader.iAttributes); + + if ((iFixedHeader.iFileNameLength > KMaxFileName) || (!iFixedHeader.iAttributes) || (!iFixedHeader.iFileNameLength)) + { + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - Leaving - iFileNameLength: %d more then MaxLength", iFixedHeader.iFileNameLength); + User::Leave(KErrOverflow); + } + + iFixedHeaderRead = ETrue; + } // if + + if (!iFileNameRead) + { + TPtr8 ptr(reinterpret_cast(const_cast(iFileName.Ptr())), iBytesRead, iFixedHeader.iFileNameLength * KCharWidthInBytes); + + if (ReadFromBufferV(ptr, iFixedHeader.iFileNameLength * KCharWidthInBytes, current, end) == EFalse) + { + iBytesRead = ptr.Size(); + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - ReadFromBufferV() returned False - Filename bytes read: %d", iBytesRead); + break; + } // if + + + iFileName.SetLength(iFixedHeader.iFileNameLength); + + // Throw away the unpacked filename, as we're now + RedirectMIDletRestorePathL(iFileName, aUnpackedFileNames); + + // We don't need the original filename any more, we're using the one returne by Redirect... + iFileName = aUnpackedFileNames[fileIndex]; + + iFileNameRead = ETrue; + + // set the index to the next file in the list + fileIndex++; + } + + // Is the file in the snapshot, if not it was deleted in an increment and does not need restoring + if (!iSnapshotChecked) + { + CheckFileInSnapshotL(); + } // if + + if (!iRestore && !iLeftToSkip) + { + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - restore not permitted, skipping file data (%d bytes)", iFixedHeader.iFileSize); + iLeftToSkip = iFixedHeader.iFileSize; // So we can skip the bytes + } + + if (iRestore) + { + // Have we opened the file? + if (!iFileOpen) + { + RecreateFileL(); + } + + // Write to the file + if (!WriteToFileL(current, end)) + { + __LOG("CBufferFileReader::ReadMIDletsFromBufferL() - WriteToFileL() returned False so breaking!"); + break; + } + } // if + else + { + // We need to skip the bytes in the data + if ((end - current) >= iLeftToSkip) + { + current += iLeftToSkip; + + // Finished reset state + Reset(); + } // if + else + { + __LOG1("CBufferFileReader::ReadMIDletsFromBufferL() - Still more data to skip...: %d bytes", iLeftToSkip); + iLeftToSkip = iLeftToSkip - (end - current); + break; + } // else + } // else + } // while + + if ((aLastSection && iFileOpen) || + (aLastSection && (iLeftToSkip > 0))) + { + User::Leave(KErrUnderflow); + } // if + } // ReadMIDletsFromBufferL + + void CBufferFileReader::Reset() + /** Resets the state of the object. + */ + { + iFileHandle.Close(); + iFileOpen = EFalse; + iFileNameRead = EFalse; + iLeftToSkip = 0; + iSnapshotChecked = EFalse; + iFileName.SetLength(0); + iFixedHeaderRead = EFalse; + iBytesRead = 0; + } + + CBufferFileReader::~CBufferFileReader() + /** destructor + */ + { + iFileHandle.Close(); + } + + + + CBufferSnapshotWriter* CBufferSnapshotWriter::NewL(RSnapshots* aSnapshots) + /** Symbian OS constructor + + @param aFiles File information to write to the buffer.ownernship transfer + */ + { + CBufferSnapshotWriter* self = new(ELeave) CBufferSnapshotWriter(aSnapshots); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } // NewL + + CBufferSnapshotWriter::CBufferSnapshotWriter(RSnapshots* aSnapshots) : iSnapshots(aSnapshots) + /** Standard C++ constructor + */ + { + } + + void CBufferSnapshotWriter::ConstructL() + /** Symbian second phase constructor + + @param aFiles File information to write to the buffer. + */ + { + __ASSERT_DEBUG(iSnapshots, Panic(KErrArgument)); + #ifdef SBE_LOGGING_ENABLED + const TInt count = iSnapshots->Count(); + __LOG1("CBufferFileReader::NewL() - Got %d snapshots to compare against during restore...", count); + + for(TInt x = 0; x < count; ++x) + { + const TDesC& snapshot = (*iSnapshots)[x]->FileName(); + __LOG3("CBufferFileReader::NewL() - snapshot[%4d/%4d] is: %S", x+1, count, &snapshot); + } // for x + + #endif + } // ConstructL + + CBufferSnapshotWriter::~CBufferSnapshotWriter() + /** Standard C++ destructor + */ + { + if(iSnapshots) + { + iSnapshots->ResetAndDestroy(); + delete iSnapshots; + } + } // ~CBufferSnapshotWriter + + void CBufferSnapshotWriter::StartL(TPtr8& aBuffer, TBool& aCompleted) + /** Starts writing to the buffer + + @param aBuffer The buffer. + @param aCompleted On return if we have finished writing data. + */ + { + __LOG("CBufferSnapshotWriter::StartL() - START"); + WriteToBufferL(aBuffer, aCompleted); + __LOG("CBufferSnapshotWriter::StartL() - END"); + } // WriteToBufferL + + void CBufferSnapshotWriter::ContinueL(TPtr8& aBuffer, TBool& aCompleted) + /** Continues writing to the buffer + + @param aBuffer The buffer. + @param aCompleted On return if we have finished writing data. + */ + { + __LOG("CBufferSnapshotWriter::ContinueL() - START"); + WriteToBufferL(aBuffer, aCompleted); + __LOG("CBufferSnapshotWriter::ContinueL() - END"); + } // WriteToBufferL + + void CBufferSnapshotWriter::WriteToBufferL(TPtr8& aBuffer, TBool& aCompleted) + /** Writes to the buffer + + @param aBuffer The buffer. + @param aCompleted On return if we have finished writing data. + */ + { + __LOG1("CBufferSnapshotWriter::WriteToBufferL() - START - aBuffer length: %d", aBuffer.Length()); + aCompleted = EFalse; + + const TUint count = iSnapshots->Count(); + while (iCurrentSnapshot < count) + { + __LOG1("CBufferSnapshotWriter::WriteToBufferL() - iCurrentSnapshot: %d", iCurrentSnapshot); + + // Check there is enough room + if (sizeof(TSnapshot) > static_cast(aBuffer.MaxSize() - aBuffer.Size())) + { + __LOG("CBufferSnapshotWriter::WriteToBufferL() - Snapshot size is more than buffer available - break"); + break; + } // if + + // Write modified + TSnapshot snapshot; + (*iSnapshots)[iCurrentSnapshot]->Snapshot(snapshot); + __LOG1("CBufferSnapshotWriter::WriteToBufferL() - writing snapshot for file: %S", &snapshot.iFileName); + + WriteToBufferF(snapshot, aBuffer); + + ++iCurrentSnapshot; + } // while + + if (iCurrentSnapshot >= count) + { + aCompleted = ETrue; + } // if + + __LOG1("CBufferSnapshotWriter::WriteToBufferL() - END - aCompleted: %d", aCompleted); + } // WriteToBufferL + + CBufferSnapshotReader* CBufferSnapshotReader::NewL(RSnapshots& aSnapshots) + /** Symbian constructor + + @param aFiles Locaton to store files read from buffer. + */ + { + return new (ELeave) CBufferSnapshotReader(aSnapshots); + } + + CBufferSnapshotReader::CBufferSnapshotReader(RSnapshots& aSnapshots) : + iSnapshots(aSnapshots) + /** C++ constructor + + @param aSnapshots snapshots of files. + */ + { + } + + CBufferSnapshotReader::~CBufferSnapshotReader() + /** + C++ destructor + */ + { + } + + void CBufferSnapshotReader::StartL(const TDesC8& aBuffer, TBool aLastSection) + /** Starts reading data from the buffer + + @param aBuffer buffer to read from. + @param aLastSection is this the last section. + */ + { + __LOG2("CBufferSnapshotReader::StartL() - START - buffer len: %d, aLastSection: %d", aBuffer.Length(), aLastSection); + + ReadFromBufferL(aBuffer, aLastSection); + + __LOG("CBufferSnapshotReader::StartL() - END"); + } + + void CBufferSnapshotReader::ContinueL(const TDesC8& aBuffer, TBool aLastSection) + /** Continues reading data from the buffer + + @param aBuffer buffer to read from. + @param aLastSection is this the last section. + */ + { + __LOG2("CBufferSnapshotReader::ContinueL() - START - buffer len: %d, aLastSection: %d", aBuffer.Length(), aLastSection); + + ReadFromBufferL(aBuffer, aLastSection); + + __LOG("CBufferSnapshotReader::ContinueL() - END"); + } + + void CBufferSnapshotReader::ReadFromBufferL(const TDesC8& aBuffer, TBool /*aLastSection*/) + /** Reads data from the buffer + + @param aBuffer buffer to read from. + @param aLastSection is this the last section. + */ + { + __LOG("CBufferSnapshotReader::ReadFromBufferL() - START"); + + TUint8* current = const_cast(aBuffer.Ptr()); + const TUint8* end = current + aBuffer.Size(); + while (current < end) + { + if (ReadFromBufferF(iSnapshot, current, end) == EFalse) + { + __LOG("CBufferSnapshotReader::ReadFromBufferL() - returned EFalse breaking!"); + break; + } + + __LOG1("CBufferSnapshotReader::ReadFromBufferL() - read snapshot info for file: %S", &iSnapshot.iFileName); + CSnapshot* snapshot = CSnapshot::NewLC(iSnapshot); + iSnapshots.AppendL(snapshot); + CleanupStack::Pop(snapshot); + } // while + + __LOG("CBufferSnapshotReader::ReadFromBufferL() - END"); + } // ReadFromBufferL + + + // CSnapshot // + + /** + + Symbian 2nd phase construction creates a CSelection + + @param aType - Selection Type + @param aSelection - Selection Nmae + @return CSelection a pointer to a new object + */ + CSnapshot* CSnapshot::NewLC(const TInt64& aModified, const TDesC& aFileName) + { + CSnapshot* self = new (ELeave) CSnapshot(aModified); + CleanupStack::PushL(self); + self->ConstructL(aFileName); + return self; + } + + /** + + Symbian 2nd phase construction creates a Selection + + @param aSnapshot - TSnapshot snapshot + @return CSelection a pointer to a new object + */ + CSnapshot* CSnapshot::NewLC(const TSnapshot& aSnapshot) + { + return CSnapshot::NewLC(aSnapshot.iModified, aSnapshot.iFileName); + } + + /** + Standard C++ destructor + */ + CSnapshot::~CSnapshot() + { + delete iFileName; + } + + /** + Standard C++ constructor + */ + CSnapshot::CSnapshot(const TInt64& aModified) : iModified(aModified) + { + } + + /** + Symbian 2nd phase constructor + */ + void CSnapshot::ConstructL(const TDesC& aFileName) + { + iFileName = aFileName.AllocL(); + } + + /** + Selection Type + + @return TSelectionType Type + */ + const TInt64& CSnapshot::Modified() const + { + return iModified; + } + + /** + Selection Name + + @return const TDesC& Name + */ + const TDesC& CSnapshot::FileName() const + { + return *iFileName; + } + + /** + Create snapshot of type TSnapshot + + @return TSnapshot snapshot + + */ + void CSnapshot::Snapshot(TSnapshot& aSnapshot) + { + aSnapshot.iFileName = *iFileName; + aSnapshot.iModified = iModified; + } + + /** + Method will be used for Sort on RPointerArray + + @param aFirst CSnapshot& snapshot to compare + @param aSecond CSnapshot& snapshot to compare + + @see RArray::Sort() + */ + TInt CSnapshot::Compare(const CSnapshot& aFirst, const CSnapshot& aSecond) + { + return aFirst.FileName().CompareF(aSecond.FileName()); + } + + /** + Method will be used for Find on RPointerArray + + @param aFirst CSnapshot& snapshot to match + @param aSecond CSnapshot& snapshot to match + + @see RArray::Find() + */ + TBool CSnapshot::Match(const CSnapshot& aFirst, const CSnapshot& aSecond) + { + return (aFirst.FileName() == aSecond.FileName()); + } + + + } // namespace conn +