persistentstorage/sql/SRC/Server/SqlBur.cpp
branchRCL_3
changeset 8 fa9941cf3867
parent 0 08ec8eefde2f
child 9 667e88a979d7
equal deleted inserted replaced
6:5ffdb8f2067f 8:fa9941cf3867
    15 
    15 
    16 #include "SqlBur.h"
    16 #include "SqlBur.h"
    17 #include "SqlAssert.h"
    17 #include "SqlAssert.h"
    18 #include "SqlPanic.h"
    18 #include "SqlPanic.h"
    19 
    19 
    20 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    21 //////////////                     Backup database file header format                           ///////////////////
       
    22 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    23 
       
    24 ////// No version (Version 0)
       
    25 //  8 chars          8 chars          8 chars             up to 256 characters (512 bytes)
       
    26 // <32-bit checksum><32-bit filesize><32-bit filenamelen><filename - UTF16 encoded>
       
    27 
       
    28 //////             Version 2
       
    29 //  8 chars          8 chars   4 chars     16 chars         8 chars             up to 256 characters (512 bytes)
       
    30 // <32-bit checksum><FFFFAA55><Version N#><64-bit filesize><32-bit filenamelen><filename - UTF16 encoded>
       
    31 
       
    32 const TInt KBackupHeaderVersion = 2;			//Current backup database file header version
       
    33 
       
    34 const TUint32 KMagicNum = 0xFFFFAA55;			//Magic number. If the "old database file size" field in the header
       
    35 												//has this value, then the header version is 2+
       
    36 const TInt KMaxHeaderSize = 256 + KMaxFileName;	//The size of the buffer used for the operations on the header
       
    37 
       
    38 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    39 
       
    40 //Extracts and returns 32-bit integer from aNumBuf buffer.
    20 //Extracts and returns 32-bit integer from aNumBuf buffer.
    41 static TUint32 GetNumUint32L(const TDesC& aNumBuf)
    21 static TUint32 GetNumUint32L(const TDesC& aNumBuf)
    42 	{
    22 	{
    43 	TLex lex(aNumBuf);
    23 	TLex lex(aNumBuf);
    44 	lex.SkipSpace();
    24 	lex.SkipSpace();
   113 	iProperty.Close();
    93 	iProperty.Close();
   114 	
    94 	
   115 	// make sure the file list is released
    95 	// make sure the file list is released
   116 	iFileList.Reset();
    96 	iFileList.Reset();
   117 	
    97 	
   118 	// the header buffer
       
   119 	delete iBuffer;
       
   120 	
       
   121 	// the file list array
    98 	// the file list array
   122 	iFileList.Close();
    99 	iFileList.Close();
   123 	
   100 	
   124 	// close the file
   101 	// close the file
   125 	iFile.Close();
   102 	iFile.Close();
   126 	
   103 	
   127 	// nuke the active backup client
   104 	// nuke the active backup client
   128 	if(iActiveBackupClient)
   105     delete iActiveBackupClient;
   129 		{
       
   130 		delete iActiveBackupClient;
       
   131 		}
       
   132 	}
   106 	}
   133 
   107 
   134 /** Standard two phase construction
   108 /** Standard two phase construction
   135 	@leave if non memory or StartL leaves
   109 	@leave if non memory or StartL leaves
   136 */	
   110 */	
   140 	__SQLLEAVE_IF_ERROR(iProperty.Attach(KUidSystemCategory,KUidBackupRestoreKey));
   114 	__SQLLEAVE_IF_ERROR(iProperty.Attach(KUidSystemCategory,KUidBackupRestoreKey));
   141 	
   115 	
   142 	// add us to the scheduler
   116 	// add us to the scheduler
   143 	CActiveScheduler::Add(this);
   117 	CActiveScheduler::Add(this);
   144 
   118 
   145 	// a place for the header info
       
   146 	iBuffer=HBufC::NewL(KMaxHeaderSize);
       
   147 
       
   148 	// set active and request notification of changes to backup
   119 	// set active and request notification of changes to backup
   149 	// and restore publish/subscribe property
   120 	// and restore publish/subscribe property
   150 	StartL();	
   121 	StartL();	
   151 	}
   122 	}
   152 
   123 
   171 /**	Kick off the BUR client
   142 /**	Kick off the BUR client
   172 	@leave if TestBurStatusL leaves
   143 	@leave if TestBurStatusL leaves
   173 */
   144 */
   174 void CSqlBackupClient::StartL()
   145 void CSqlBackupClient::StartL()
   175 	{
   146 	{
   176 	if(!IsActive())
   147     TestBurStatusL();
   177 		{
   148     NotifyChange();
   178 		TestBurStatusL();
       
   179 		NotifyChange();
       
   180 		}
       
   181 	}
   149 	}
   182 
   150 
   183 /** Resubscribe and wait for events
   151 /** Resubscribe and wait for events
   184 */	
   152 */	
   185 void CSqlBackupClient::NotifyChange()
   153 void CSqlBackupClient::NotifyChange()
   200 	if(iProperty.Get(status)!=KErrNotFound)
   168 	if(iProperty.Get(status)!=KErrNotFound)
   201 		{
   169 		{
   202 		status&=KBURPartTypeMask;
   170 		status&=KBURPartTypeMask;
   203 		switch(status)
   171 		switch(status)
   204 			{
   172 			{
   205 			case EBURUnset:
   173 			case EBURUnset: // same as EBURNormal
   206 				// same as EBURNormal
       
   207 			case EBURNormal:
   174 			case EBURNormal:
   208 				if(iActiveBackupClient)
   175 				delete iActiveBackupClient;
   209 					{
   176 				iActiveBackupClient=NULL;
   210 					delete iActiveBackupClient;
       
   211 					iActiveBackupClient=NULL;
       
   212 					}
       
   213 				break;
   177 				break;
   214 			case EBURBackupFull:
   178 			case EBURBackupFull:
   215 			case EBURBackupPartial:
   179 			case EBURBackupPartial:
   216 				// we only do full backups
   180             case EBURRestoreFull:
   217 				if(!iActiveBackupClient)
   181             case EBURRestorePartial:
   218 					{
   182 				// we only do full backups and full restores
   219 					iActiveBackupClient=CActiveBackupClient::NewL(this);
       
   220 					}
       
   221 				iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
       
   222 				break;
       
   223 			case EBURRestoreFull:
       
   224 			case EBURRestorePartial:
       
   225 				// we only do full restores
       
   226 				if(!iActiveBackupClient)
   183 				if(!iActiveBackupClient)
   227 					{
   184 					{
   228 					iActiveBackupClient=CActiveBackupClient::NewL(this);
   185 					iActiveBackupClient=CActiveBackupClient::NewL(this);
   229 					}
   186 					}
   230 				iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
   187 				iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
   320 					// empty or unreadable - skip this file
   277 					// empty or unreadable - skip this file
   321 					iState=EBackupEndOfFile;
   278 					iState=EBackupEndOfFile;
   322 					break;
   279 					break;
   323 					}
   280 					}
   324 				
   281 				
   325 				// build the header - this is an instance member because it
       
   326 				// has to persist over multiple calls to this method
       
   327 				TPtr hdrPtr=iBuffer->Des();
       
   328 				
       
   329 				// get the checksum - only grab last 4 bytes - enough to be satisfied that
   282 				// get the checksum - only grab last 4 bytes - enough to be satisfied that
   330 				// the backup and restore worked ok
   283 				// the backup and restore worked ok
   331 				TUint32 checksum = CheckSumL(iFile) & 0xFFFFFFFF;
   284 				TUint32 checksum = CheckSumL(iFile) & KMaxTUint32;
   332 
   285 
   333 				// build the header
   286                 // build the header - this is an instance member because it
       
   287                 // has to persist over multiple calls to this method
   334 				const TDesC& fileName = iFileList[iFileIndex].FullName();
   288 				const TDesC& fileName = iFileList[iFileIndex].FullName();
   335 				hdrPtr.Format(_L("%8x%8x%4x%16lx%8x%S"),
   289 				iBuffer.Format(_L("%8x%8x%4x%16lx%8x%S"),
   336 					checksum,					// %8x
   290 					checksum,					// %8x
   337 					KMagicNum,					// %8x
   291 					KMagicNum,					// %8x
   338 					KBackupHeaderVersion,		// %4x
   292 					KBackupHeaderVersion,		// %4x
   339 					fileSize,					// %16lx
   293 					fileSize,					// %16lx
   340 					fileName.Length(),			// %8x
   294 					fileName.Length(),			// %8x
   341 					&fileName);					// %S
   295 					&fileName);					// %S
   342 				
   296 				
   343 				// we need it to look like an 8bit buffer
   297 				// we need it to look like an 8bit buffer
   344 				TPtr8 hdrPtr8((TUint8*)hdrPtr.Ptr(),hdrPtr.Size(),hdrPtr.Size());
   298 				TPtr8 hdrPtr8((TUint8*)iBuffer.Ptr(), iBuffer.Size(), iBuffer.Size());
   345 							
   299 							
   346 				TInt len = Min(hdrPtr8.Size(), bufFreeSpace);
   300 				TInt len = Min(hdrPtr8.Size(), bufFreeSpace);
   347 				
   301 				
   348 				// append the header to the buffer (only till it's full)
   302 				// append the header to the buffer (only till it's full)
   349 				aBuffer.Append(hdrPtr8.Ptr(), len);
   303 				aBuffer.Append(hdrPtr8.Ptr(), len);
   366 				break;
   320 				break;
   367 				}
   321 				}
   368 			case EBackupOpenPartHeaderSent: // need to send the rest of the header
   322 			case EBackupOpenPartHeaderSent: // need to send the rest of the header
   369 				{
   323 				{
   370 				// get back the header - this is already loaded with the necessary info
   324 				// get back the header - this is already loaded with the necessary info
   371 				// from the previous state we were in
   325 				// from the previous state we were in - EBackupOpenNothingSent
   372 				TPtr hdrPtr = iBuffer->Des();
       
   373 				
   326 				
   374 				// we need it to look like an 8bit buffer
   327 				// we need it to look like an 8bit buffer
   375 				TPtr8 hdrPtr8((TUint8*)hdrPtr.Ptr(),hdrPtr.Size(),hdrPtr.Size());
   328 				TPtr8 hdrPtr8((TUint8*)iBuffer.Ptr(), iBuffer.Size(), iBuffer.Size());
   376 				
   329 				
   377 				// how many bytes have we yet to send?
   330 				// how many bytes have we yet to send?
   378 				TInt bytesRemaining = hdrPtr.Size() - iHeaderSent;
   331 				TInt bytesRemaining = hdrPtr8.Size() - iHeaderSent;
   379 				TInt len = Min(bytesRemaining, bufFreeSpace);
   332 				TInt len = Min(bytesRemaining, bufFreeSpace);
   380 				aBuffer.Append(hdrPtr8.Ptr() + iHeaderSent, len);
   333 				aBuffer.Append(hdrPtr8.Ptr() + iHeaderSent, len);
   381 				
   334 				
   382 				if(bytesRemaining <= bufFreeSpace)
   335 				if(bytesRemaining <= bufFreeSpace)
   383 					{
   336 					{
   454 	@param TDriveNumber the drive to restore (unused)
   407 	@param TDriveNumber the drive to restore (unused)
   455 	@leave
   408 	@leave
   456 */
   409 */
   457 void CSqlBackupClient::InitialiseRestoreProxyBaseDataL(TSecureId aSid, TDriveNumber /* aDrive */)
   410 void CSqlBackupClient::InitialiseRestoreProxyBaseDataL(TSecureId aSid, TDriveNumber /* aDrive */)
   458 	{
   411 	{
   459 	iBuffer->Des().Zero();
   412 	iBuffer.Zero();
   460 	// this is the first state of the restore state machine
   413 	// this is the first state of the restore state machine
   461 	iState=ERestoreExpectChecksum;
   414 	iState=ERestoreExpectChecksum;
   462 	iAnyData=EFalse; // to keep track in the state machine whether any data was actually sent
   415 	iAnyData=EFalse; // to keep track in the state machine whether any data was actually sent
   463 	// save the sid for notifying the server when the restore is done
   416 	// save the sid for notifying the server when the restore is done
   464 	iSid=aSid;
   417 	iSid=aSid;
   479 	// used to walk the buffer
   432 	// used to walk the buffer
   480 	// got a new buffer - because each time this method is called, we have a
   433 	// got a new buffer - because each time this method is called, we have a
   481 	// fresh chunk of data
   434 	// fresh chunk of data
   482 	TInt inBufferPos = 0;
   435 	TInt inBufferPos = 0;
   483 
   436 
   484 	// convert the buffer - this is KMaxHeaderSize=256+KMaxFileName
       
   485 	TPtr outBufPtr = iBuffer->Des();	
       
   486 	
       
   487 	// to mark when the state machine is through
   437 	// to mark when the state machine is through
   488 	TBool done = EFalse;
   438 	TBool done = EFalse;
   489 	
   439 	
   490 	// check whether this is an empty restore
   440 	// check whether this is an empty restore
   491 	if(aFinishedFlag && !iAnyData)
   441 	if(aFinishedFlag && !iAnyData)
   525 		switch(iState)
   475 		switch(iState)
   526 			{
   476 			{
   527 			case ERestoreExpectChecksum: // 16 bytes (the header is UTF16 encoded, 8 unicode characters for the checksum)
   477 			case ERestoreExpectChecksum: // 16 bytes (the header is UTF16 encoded, 8 unicode characters for the checksum)
   528 				{
   478 				{
   529 				const TInt KCheckSumStrLen = 8;
   479 				const TInt KCheckSumStrLen = 8;
   530 				CopyBufData(aInBuffer, inBufferPos, outBufPtr, KCheckSumStrLen);
   480 				CopyBufData(aInBuffer, inBufferPos, iBuffer, KCheckSumStrLen);
   531 				if(outBufPtr.Length() == KCheckSumStrLen)
   481 				if(iBuffer.Length() == KCheckSumStrLen)
   532 					{
   482 					{
   533 					iChecksum = ::GetNumUint32L(outBufPtr);
   483 					iChecksum = ::GetNumUint32L(iBuffer);
   534 					iState = ERestoreExpectOldFileSize;
   484 					iState = ERestoreExpectOldFileSize;
   535 					outBufPtr.Zero();
   485 					iBuffer.Zero();
   536 					}
   486 					}
   537 				break;
   487 				break;
   538 				}
   488 				}
   539 			case ERestoreExpectOldFileSize: // 16 bytes (the header is UTF16 encoded, 8 unicode characters for 32-bit old file size)
   489 			case ERestoreExpectOldFileSize: // 16 bytes (the header is UTF16 encoded, 8 unicode characters for 32-bit old file size)
   540 				{
   490 				{
   541 				const TInt KOldFileSizeStrLen = 8;
   491 				const TInt KOldFileSizeStrLen = 8;
   542 				CopyBufData(aInBuffer, inBufferPos, outBufPtr, KOldFileSizeStrLen);
   492 				CopyBufData(aInBuffer, inBufferPos, iBuffer, KOldFileSizeStrLen);
   543 				if(outBufPtr.Length() == KOldFileSizeStrLen)
   493 				if(iBuffer.Length() == KOldFileSizeStrLen)
   544 					{
   494 					{
   545 					TUint32 oldFileSize = ::GetNumUint32L(outBufPtr);
   495 					TUint32 oldFileSize = ::GetNumUint32L(iBuffer);
   546 					if(oldFileSize == KMagicNum)
   496 					if(oldFileSize == KMagicNum)
   547 						{
   497 						{
   548 						iState = ERestoreExpectVersion;
   498 						iState = ERestoreExpectVersion;
   549 						}
   499 						}
   550 					else
   500 					else
   551 						{
   501 						{
   552 						iFileSize = oldFileSize;	
   502 						iFileSize = oldFileSize;	
   553 						iState = ERestoreExpectFileNameSize;
   503 						iState = ERestoreExpectFileNameSize;
   554 						}
   504 						}
   555 					outBufPtr.Zero();
   505 					iBuffer.Zero();
   556 					}
   506 					}
   557 				break;
   507 				break;
   558 				}	
   508 				}	
   559 			case ERestoreExpectVersion:
   509 			case ERestoreExpectVersion:
   560 				{
   510 				{
   561 				const TInt KVersionStrLen = 4;
   511 				const TInt KVersionStrLen = 4;
   562 				CopyBufData(aInBuffer, inBufferPos, outBufPtr, KVersionStrLen);
   512 				CopyBufData(aInBuffer, inBufferPos, iBuffer, KVersionStrLen);
   563 				if(outBufPtr.Length() == KVersionStrLen)
   513 				if(iBuffer.Length() == KVersionStrLen)
   564 					{
   514 					{
   565 					//Ignore the version: ::GetNumUint32L(outBufPtr);	
   515 					//Ignore the version: ::GetNumUint32L(iBuffer);	
   566 					//At this stage we know that the version is 2+
   516 					//At this stage we know that the version is 2+
   567 					iState = ERestoreExpectFileSize;
   517 					iState = ERestoreExpectFileSize;
   568 					outBufPtr.Zero();
   518 					iBuffer.Zero();
   569 					}
   519 					}
   570 				break;
   520 				break;
   571 				}
   521 				}
   572 			case ERestoreExpectFileSize:
   522 			case ERestoreExpectFileSize:
   573 				{
   523 				{
   574 				const TInt KFileSizeStrLen = 16;
   524 				const TInt KFileSizeStrLen = 16;
   575 				CopyBufData(aInBuffer, inBufferPos, outBufPtr, KFileSizeStrLen);
   525 				CopyBufData(aInBuffer, inBufferPos, iBuffer, KFileSizeStrLen);
   576 				if(outBufPtr.Length() == KFileSizeStrLen)
   526 				if(iBuffer.Length() == KFileSizeStrLen)
   577 					{
   527 					{
   578 					iFileSize = GetNumInt64L(outBufPtr);	
   528 					iFileSize = GetNumInt64L(iBuffer);	
   579 					iState = ERestoreExpectFileNameSize;
   529 					iState = ERestoreExpectFileNameSize;
   580 					outBufPtr.Zero();
   530 					iBuffer.Zero();
   581 					}
   531 					}
   582 				break;
   532 				break;
   583 				}
   533 				}
   584 			case ERestoreExpectFileNameSize: // the size of the file name to restore
   534 			case ERestoreExpectFileNameSize: // the size of the file name to restore
   585 				{
   535 				{
   586 				const TInt KFileNameLenStrLen = 8;
   536 				const TInt KFileNameLenStrLen = 8;
   587 				CopyBufData(aInBuffer, inBufferPos, outBufPtr, KFileNameLenStrLen);
   537 				CopyBufData(aInBuffer, inBufferPos, iBuffer, KFileNameLenStrLen);
   588 				if(outBufPtr.Length() == KFileNameLenStrLen)
   538 				if(iBuffer.Length() == KFileNameLenStrLen)
   589 					{
   539 					{
   590 					iFileNameSize = GetNumUint32L(outBufPtr);		
   540 					iFileNameSize = GetNumUint32L(iBuffer);		
   591 					iState = ERestoreExpectFileName;
   541 					iState = ERestoreExpectFileName;
   592 					outBufPtr.Zero();
   542 					iBuffer.Zero();
   593 					}
   543 					}
   594 				break;
   544 				break;
   595 				}
   545 				}
   596 			case ERestoreExpectFileName:  // the name of the file to restore
   546 			case ERestoreExpectFileName:  // the name of the file to restore
   597 				{
   547 				{
   598 				CopyBufData(aInBuffer, inBufferPos, outBufPtr, iFileNameSize);
   548 				CopyBufData(aInBuffer, inBufferPos, iBuffer, iFileNameSize);
   599 				if(outBufPtr.Length() == iFileNameSize)
   549 				if(iBuffer.Length() == iFileNameSize)
   600 					{
   550 					{
   601 					iState = ERestoreExpectData;
   551 					iState = ERestoreExpectData;
   602 					outBufPtr.Append(KRestoreSuffix);
   552 					iBuffer.Append(KRestoreSuffix);
   603 					// now we start writing the data to the target file
   553 					// now we start writing the data to the target file
   604 					// write to a temp - double disk space potentially
   554 					// write to a temp - double disk space potentially
   605 					// once all the temp files are created, then they are renamed to the
   555 					// once all the temp files are created, then they are renamed to the
   606 					// real file names in one fell swoop
   556 					// real file names in one fell swoop
   607 					__SQLLEAVE_IF_ERROR(iFile.Replace(iInterface->Fs(), outBufPtr, EFileWrite | EFileShareExclusive));
   557 					__SQLLEAVE_IF_ERROR(iFile.Replace(iInterface->Fs(), iBuffer, EFileWrite | EFileShareExclusive));
   608 					outBufPtr.Zero();
   558 					iBuffer.Zero();
   609 					}
   559 					}
   610 				break;
   560 				break;
   611 				}
   561 				}
   612 			case ERestoreExpectData: // now for the data
   562 			case ERestoreExpectData: // now for the data
   613 				{
   563 				{
   622 				break;
   572 				break;
   623 				}
   573 				}
   624 			case ERestoreComplete: // file completely restored
   574 			case ERestoreComplete: // file completely restored
   625 				{
   575 				{
   626 				// calculate the checksum
   576 				// calculate the checksum
   627 				TUint32 cksum = CheckSumL(iFile) & 0xFFFFFFFF;
   577 				TUint32 cksum = CheckSumL(iFile) & KMaxTUint32;
   628 				
   578 				
   629 				// validate that the checksum matches
       
   630 				if(cksum!=iChecksum)
       
   631 					{
       
   632 					__SQLLEAVE(KErrCorrupt);
       
   633 					}
       
   634 
       
   635 				// done with the file now - has to follow checksum cos it
   579 				// done with the file now - has to follow checksum cos it
   636 				// expects ann open file
   580 				// expects an open file
       
   581                 __SQLLEAVE_IF_ERROR(iFile.Flush());
   637 				iFile.Close();
   582 				iFile.Close();
   638 
   583 
       
   584                 // validate that the checksum matches
       
   585                 if(cksum!=iChecksum)
       
   586                     {
       
   587                     __SQLLEAVE(KErrCorrupt);
       
   588                     }
       
   589 				
   639 				// end of data - or another file to be restored?
   590 				// end of data - or another file to be restored?
   640 				if(aFinishedFlag)
   591 				if(aFinishedFlag)
   641 					{
   592 					{
   642 					// we need to rename all the
   593 					// we need to rename all the
   643 					// temp rst files to the real database names
   594 					// temp rst files to the real database names
   645 					__SQLLEAVE_IF_ERROR(iInterface->Fs().GetDir(KRestoreFilter,KEntryAttNormal,ESortNone,dir));
   596 					__SQLLEAVE_IF_ERROR(iInterface->Fs().GetDir(KRestoreFilter,KEntryAttNormal,ESortNone,dir));
   646 					CleanupStack::PushL(dir);
   597 					CleanupStack::PushL(dir);
   647 					for(TInt a=0;a<dir->Count();++a)
   598 					for(TInt a=0;a<dir->Count();++a)
   648 						{
   599 						{
   649 						TEntry entry=(*dir)[a];
   600 						TEntry entry=(*dir)[a];
   650 						TPtr rst=entry.iName.Des();
   601 						TPtrC rst=entry.iName.Des();
   651 						TInt len=rst.Length();
   602 						TInt len=rst.Length();
   652 						// format <filename>.db.bak.rst
   603 						// format <filename>.db.bak.rst
   653 						// just a convenience!
   604 						// just a convenience!
   654 						TBufC<KMaxFileName> bak(rst.LeftTPtr(len-4));
   605 						TPtrC bak(rst.Left(len - 4));//".rst" part excluded
   655 						TBufC<KMaxFileName> db(rst.LeftTPtr(len-8));
   606 						TPtrC db(rst.Left(len - 8));//".bak.rst" part excluded
   656 						
   607 						
   657 						// first, rename the orig .db as .bak just in case
   608 						// first, rename the orig .db as .bak just in case
   658 						// ok if not found - might have been deleted.
   609 						// ok if not found - might have been deleted.
   659 						//the ".bak" file, if exists, will be deleted first.
   610 						//the ".bak" file, if exists, will be deleted first.
   660 						(void)iInterface->Fs().Delete(bak);
   611 						(void)iInterface->Fs().Delete(bak);
   683 					__SQLLEAVE_IF_ERROR(iInterface->Fs().GetDir(KBackupFilter,KEntryAttNormal,ESortNone,dir));
   634 					__SQLLEAVE_IF_ERROR(iInterface->Fs().GetDir(KBackupFilter,KEntryAttNormal,ESortNone,dir));
   684 					CleanupStack::PushL(dir);
   635 					CleanupStack::PushL(dir);
   685 					for(TInt a1=0;a1<dir->Count();++a1)
   636 					for(TInt a1=0;a1<dir->Count();++a1)
   686 						{
   637 						{
   687 						TEntry entry=(*dir)[a1];
   638 						TEntry entry=(*dir)[a1];
   688 						TPtr bak=entry.iName.Des();
   639 						TPtrC bak=entry.iName.Des();
   689 						__SQLLEAVE_IF_ERROR(iInterface->Fs().Delete(bak));
   640 						__SQLLEAVE_IF_ERROR(iInterface->Fs().Delete(bak));
   690 						}
   641 						}
   691 					
   642 					
   692 					// clean up dir
   643 					// clean up dir
   693 					//delete dir;
   644 					//delete dir;
   726 		return;
   677 		return;
   727 		}
   678 		}
   728 	for(TInt a=0;a<dir->Count();++a)
   679 	for(TInt a=0;a<dir->Count();++a)
   729 		{
   680 		{
   730 		TEntry entry=(*dir)[a];
   681 		TEntry entry=(*dir)[a];
   731 		TPtr bak=entry.iName.Des();
   682 		TPtrC bak=entry.iName.Des();
   732 		TInt len=bak.Length();
   683 		TInt len=bak.Length();
   733 		TBufC<KMaxFileName> db(bak.LeftTPtr(len-4));
   684 		TPtrC db(bak.Left(len-4));//".bak" part excluded
   734 		rc=iInterface->Fs().Delete(db); // rename does not overwrite
   685 		rc=iInterface->Fs().Delete(db); // rename does not overwrite
   735 		if(KErrNone!=rc)
   686 		if(KErrNone == rc)
   736 			{
   687 			{
   737 			// nothing happened, still have bak file (and new db)
   688 	        rc = iInterface->Fs().Rename(bak,db);
   738 			delete dir;
       
   739 			return;
       
   740 			}
   689 			}
   741 		rc=iInterface->Fs().Rename(bak,db);
   690         //The function cannot leave or return an error. The only thing which could be done here is to print out something
   742 		if(KErrNone!=rc)
   691 		//and continue with the next file.
   743 			{
   692 		if(KErrNone != rc)
   744 			// still have bak file, but db is gone!
   693 		    {
   745 			delete dir;
   694 		    RDebug::Print(_L(" *** CSqlBackupClient::TerminateMultiStageOperation(), file \"%S\", err=%d\r\n"), &db, rc);
   746 			return;
   695 		    }
   747 			}
       
   748 		// backup restored ok
   696 		// backup restored ok
   749 		}
   697 		}
   750 	// cleanup dir
   698 	// cleanup dir
   751 	delete dir;
   699 	delete dir;
   752 	}
   700 	}