--- /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 <connect/panic.h>
+
+namespace conn
+ {
+ template<class T>
+ 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<sizeof(T)> 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<TUint8*>(SBuffer.Ptr());
+
+ appCurrent += sizeof(T) - size;
+
+ ret = ETrue;
+ } // if
+ else
+ {
+ // Is there enough room in current
+ if ((apEnd - appCurrent) < static_cast<TInt>(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<TUint8*>(&aT);
+ for (TUint x = 0; x < sizeof(T); x++)
+ {
+ *ptrOut++ = *ptr++;
+ } // for
+
+ SBuffer.SetLength(0);
+ }
+
+ return ret;
+ }
+
+ template TBool ReadFromBufferF<TFileFixedHeader>(TFileFixedHeader&, TUint8*&, const TUint8*);
+ template TBool ReadFromBufferF<TSnapshot>(TSnapshot&, TUint8*&, const TUint8*);
+
+ template<class T>
+ 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<TInt>(sizeof(T)))
+ {
+ aPtr.Append(reinterpret_cast<TUint8*>(&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<TUint8*>(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<TUint8*>(const_cast<TUint16*>(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<TUint8*>(const_cast<TUint16*>(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<TUint8*>(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<TUint8*>(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<TUint8*>(const_cast<TUint16*>(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<TUint8*>(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<TUint8*>(const_cast<TUint16*>(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<TUint>(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<TUint8*>(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
+