installationservices/swi/source/integrityservices/integrityservices.cpp
changeset 0 ba25891c3a9e
child 17 741e5bba2bd1
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * CIntegrityServices implementation
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /**
       
    21  @file 
       
    22  @released
       
    23  @internalTechnology
       
    24 */
       
    25 
       
    26 #include "integrityservices.h"
       
    27 #include "journal.h"
       
    28 #include "log.h"
       
    29 #include "cleanuputils.h"
       
    30 #include "operationfunctions.h"
       
    31 
       
    32 
       
    33 #include <f32file.h>
       
    34 
       
    35 using namespace Swi;
       
    36 
       
    37 namespace Swi
       
    38 {
       
    39 /**
       
    40  * This is a trivial C class that just encapsulates a TEntryArray object in order to 
       
    41  * facilitate its storage on the heap.
       
    42  *
       
    43  * @released
       
    44  * @internalComponent 
       
    45  */
       
    46 class CEntryArray : public CBase
       
    47 	{
       
    48 public:
       
    49 	inline TEntryArray& operator()();
       
    50 
       
    51 private:
       
    52 	/**
       
    53 	 * Container to hold file entries
       
    54 	 */
       
    55 	TEntryArray iEntryArray;
       
    56 	};
       
    57 
       
    58 inline TEntryArray& CEntryArray::operator()()
       
    59 	{
       
    60 	return iEntryArray;
       
    61 	}
       
    62 } //namespace
       
    63 
       
    64 EXPORT_C CIntegrityServices* CIntegrityServices::NewL(TInt64 aTransactionID, const TDesC& aPath)
       
    65 	{
       
    66 	CIntegrityServices* self = CIntegrityServices::NewLC(aTransactionID, aPath);
       
    67 	CleanupStack::Pop(self);
       
    68 	return self;
       
    69 	}
       
    70 
       
    71 EXPORT_C CIntegrityServices* CIntegrityServices::NewLC(TInt64 aTransactionID, const TDesC& aPath)
       
    72 	{
       
    73 	CIntegrityServices* self = new(ELeave) CIntegrityServices(aTransactionID);
       
    74 	CleanupStack::PushL(self);
       
    75 	self->ConstructL(aPath);
       
    76 	return self;
       
    77 	}
       
    78 
       
    79 EXPORT_C CIntegrityServices::CIntegrityServices(TInt64 aTransactionID) : iTransactionID(aTransactionID)
       
    80 	{
       
    81 	}
       
    82 
       
    83 EXPORT_C CIntegrityServices::~CIntegrityServices()
       
    84 	{
       
    85 	delete iJournal;
       
    86 	iFs.Close();
       
    87 	
       
    88 	iLoader.Close();
       
    89 	}
       
    90 
       
    91 EXPORT_C void CIntegrityServices::ConstructL(const TDesC& aPath)
       
    92 	{
       
    93 	DEBUG_PRINTF2(_L8("Integrity Services - Opening session with  Session ID %Ld."), iTransactionID);
       
    94 	
       
    95 	// check that the supplied path is valid
       
    96 	User::LeaveIfError(iFs.Connect());
       
    97 	User::LeaveIfError(iFs.IsValidName(aPath));
       
    98 	
       
    99 	User::LeaveIfError(iLoader.Connect());
       
   100 	
       
   101 	// store the journal path and create the journal
       
   102 	TParsePtrC pathPtr(aPath);
       
   103 	iJournalPath = pathPtr.Path();
       
   104 	iJournal = CJournal::NewL(iFs, iLoader, iTransactionID, iJournalPath);
       
   105 	iSystemDrive = RFs::GetSystemDrive();
       
   106 	}
       
   107 	
       
   108 void CIntegrityServices::SimulatePowerFailureL(TFailType /*aFailType*/, TFailPosition /*aFailPosition*/, const TDesC& /*aFailFileName*/)
       
   109 	{
       
   110 	// only implemented in derived test class
       
   111 	}
       
   112 
       
   113 /*static*/ void CIntegrityServices::NormalizeDirectoryName(TDes& aFileName)
       
   114 {
       
   115 	// Directories are represented in the integrity tree and integrity journal exactly as files,
       
   116 	// without the trailing slash 
       
   117 	TInt lastCharPos = aFileName.Length() - 1;
       
   118 	if ( lastCharPos >= 0 && aFileName[lastCharPos] == KPathDelimiter &&
       
   119 		 aFileName.Locate(KPathDelimiter) != lastCharPos) // Take care not to remove slash from "c:\" and the like
       
   120 		{
       
   121 		aFileName.Delete(lastCharPos, 1);
       
   122 		}			
       
   123 }
       
   124 
       
   125 EXPORT_C void CIntegrityServices::AddL(const TDesC& aFileName)
       
   126 	{
       
   127 	DEBUG_PRINTF3(_L("Integrity Services - Session %Ld, Adding File: %S."),
       
   128 		iTransactionID, &aFileName);
       
   129 
       
   130 	HBufC* localFilenameHeap = aFileName.AllocLC();
       
   131 	TPtr localFilename = localFilenameHeap->Des();
       
   132 	NormalizeDirectoryName(localFilename); // If it is a directory name, make sure to normalize it
       
   133 		
       
   134 	// Record the added file or directory in the journal
       
   135 	SimulatePowerFailureL(EFailAddingNewFile, EBeforeJournal, aFileName);
       
   136 	iJournal->AddL(localFilename);
       
   137 	SimulatePowerFailureL(EFailAddingNewFile, EAfterJournal, aFileName);
       
   138 	CleanupStack::PopAndDestroy(localFilenameHeap);
       
   139 	}
       
   140 
       
   141 void CIntegrityServices::CopyToBackupL(const TDesC& aSource, const TDesC& aBackup)
       
   142 	{
       
   143 	// Copying a file isn't atomic so we create a temporary backup file first
       
   144 	RBuf backupTmpName;
       
   145 	backupTmpName.Create(aBackup.Length() + 4);
       
   146 	CleanupClosePushL(backupTmpName);
       
   147 	backupTmpName.Copy(aBackup);
       
   148 	_LIT(KTmpExt, ".tmp");
       
   149 	backupTmpName.Append(KTmpExt);
       
   150 	
       
   151 	// Copying a file is not an atomic operation so add the temporary
       
   152 	// file to the journal to enable cleanup if a power failure occurs before
       
   153 	// the rename
       
   154 	SimulatePowerFailureL(EFailAddingTempFile, EBeforeJournal, backupTmpName);
       
   155 	iJournal->TemporaryL(backupTmpName);
       
   156 	SimulatePowerFailureL(EFailAddingTempFile, EAfterJournal, backupTmpName);	
       
   157 		
       
   158 	CFileMan* fileMan = CFileMan::NewL(iFs);
       
   159 	CleanupStack::PushL(fileMan);
       
   160 		
       
   161 	TInt err = fileMan->Copy(aSource, backupTmpName);
       
   162 	DEBUG_PRINTF4(_L("CopyToBackupL: Copying %S to %S, err %d"), &aSource, &backupTmpName, err);
       
   163 	User::LeaveIfError(err);
       
   164 	
       
   165 	// Backup is complete, use RFs::Rename as atomic 'commit' of backup
       
   166 	err = iFs.Rename(backupTmpName, aBackup);			
       
   167 	DEBUG_PRINTF2(_L("CopyToBackupL: Commit backup returned error %d"), err);	
       
   168 	User::LeaveIfError(err);	
       
   169 	CleanupStack::PopAndDestroy(2, &backupTmpName); // backupTmpName, fileMan 
       
   170 	
       
   171 	//  Now the backup is safe the original can be deleted
       
   172 	err = iLoader.Delete(aSource);
       
   173 	DEBUG_PRINTF3(_L("CopyToBackupL: RLoader::Delete %S returned error %d"), &aSource, err);
       
   174 	User::LeaveIfError(err);
       
   175 	}
       
   176 	
       
   177 EXPORT_C void CIntegrityServices::RemoveL(const TDesC& aFileName)
       
   178 	{
       
   179 	DEBUG_PRINTF3(_L("Integrity Services - Session %Ld, Removing File: %S"), iTransactionID, &aFileName);
       
   180 
       
   181 	// before doing anything check that the file or directory exists
       
   182 	TEntry entry;
       
   183 	User::LeaveIfError(iFs.Entry(aFileName, entry));
       
   184 	
       
   185 	// We might need to grow this buffer by one byte later
       
   186 	HBufC* localFilenameHeap = HBufC::NewLC(aFileName.Length() + 1);
       
   187 	TPtr localFilename = localFilenameHeap->Des();
       
   188 	localFilename.Copy(aFileName);
       
   189 	
       
   190 	TBool isFilenameDir = entry.IsDir();
       
   191 	// The "if" below is not functionally necessary, but it is a slight optimization - 
       
   192 	// so that we won't attempt to normalize directory name on files. The optimization is not
       
   193 	// done in AddL or NormalizeDirectoryName itself, since we don't have future use for TEntry there, and the cost for RFs::Entry overweighs the one for NormalizeDirectoryName
       
   194 	if ( isFilenameDir ) 
       
   195 		{
       
   196 		NormalizeDirectoryName(localFilename);
       
   197 		}
       
   198 
       
   199 	RBuf backupFileName;
       
   200 	backupFileName.CreateL(KMaxFileName);
       
   201 	CleanupClosePushL(backupFileName);
       
   202 	SimulatePowerFailureL(EFailRemovingFile, EBeforeJournal, aFileName);
       
   203 	iJournal->RemoveL(localFilename, backupFileName);
       
   204 		
       
   205 	if (backupFileName.Length())
       
   206 		{
       
   207 		SimulatePowerFailureL(EFailRemovingFile, EAfterJournal, aFileName);
       
   208 
       
   209 		TInt err = iFs.MkDirAll(backupFileName);
       
   210 		if(err != KErrNone && err != KErrAlreadyExists)
       
   211 			{
       
   212 			User::Leave(err);
       
   213 			}
       
   214 
       
   215 		SimulatePowerFailureL(EFailRemovingFile, EBeforeAction, aFileName);
       
   216 		
       
   217 		_LIT(KSysBinMatch, "?:\\sys\\bin\\*");
       
   218 		if (localFilename.MatchF(KSysBinMatch) == 0)
       
   219 			{
       
   220 			// A copy is slower than a rename to only use the 
       
   221 			// demand paging safe API for files in sys\bin
       
   222 			CopyToBackupL(localFilename, backupFileName);			
       
   223 			}
       
   224 		else
       
   225 			{
       
   226 			err = iFs.Rename(localFilename, backupFileName);
       
   227 			DEBUG_PRINTF4(_L("Renamed %S as %S error %d"), &localFilename, &backupFileName, err);
       
   228 			User::LeaveIfError(err);
       
   229 			}				
       
   230 		SimulatePowerFailureL(EFailRemovingFile, EAfterAction, aFileName);
       
   231 		}
       
   232 	else
       
   233 		{
       
   234 		DEBUG_PRINTF2(_L("%S already backed up"), &aFileName);
       
   235 		SimulatePowerFailureL(EFailRemovingFile, EBeforeAction, aFileName);
       
   236 		// If backupFileName is zero-length, the file was added earlier
       
   237 		// in the same journal and doesn't need to be backed up.
       
   238 		if (isFilenameDir)
       
   239 			{
       
   240 			CFileMan* fileman = CFileMan::NewL(iFs);
       
   241 			CleanupStack::PushL(fileman);			
       
   242 			// Make sure to append slash before calling RmDir - otherwise it deletes the parent directory
       
   243 			if (localFilename[localFilename.Length()-1] != KPathDelimiter)
       
   244 	  			{
       
   245   				localFilename.Append(KPathDelimiter);
       
   246   				}			
       
   247 			User::LeaveIfError(fileman->RmDir(localFilename)); // A directory cannot be a paged exec., so we don't have to use iLoader
       
   248 			CleanupStack::PopAndDestroy(fileman);
       
   249 			}
       
   250 		else
       
   251 			{
       
   252 			User::LeaveIfError(iLoader.Delete(aFileName));
       
   253 			}
       
   254 		SimulatePowerFailureL(EFailRemovingFile, EAfterAction, aFileName);			
       
   255 		}
       
   256 
       
   257 	// Don't leave an empty directory structure, try pruning it
       
   258 	RemoveDirectoryTreeL(iFs, aFileName);
       
   259 
       
   260 	CleanupStack::PopAndDestroy(2, localFilenameHeap); // backupFileName
       
   261 	}
       
   262 
       
   263 EXPORT_C void CIntegrityServices::TemporaryL(const TDesC& aFileName)
       
   264 	{
       
   265 	DEBUG_PRINTF3(_L("Integrity Services - Session %Ld, Temporary File: %S."),
       
   266 		iTransactionID, &aFileName);
       
   267 
       
   268 	// record the temporary file or directory in the journal
       
   269 	SimulatePowerFailureL(EFailAddingTempFile, EBeforeJournal, aFileName);
       
   270 	iJournal->TemporaryL(aFileName);
       
   271 	SimulatePowerFailureL(EFailAddingTempFile, EAfterJournal, aFileName);
       
   272 	}
       
   273 
       
   274 EXPORT_C void CIntegrityServices::CommitL()
       
   275 	{
       
   276 	DEBUG_PRINTF2(_L8("Integrity Services - Commiting Session %Ld."), iTransactionID);
       
   277 	iJournal->SynchL();
       
   278 	iJournal->StartCommitL();
       
   279 	
       
   280 	SimulatePowerFailureL(EFailInstallComplete, EBeforeJournal, KNullDesC);
       
   281 	iJournal->WriteJournalEventL(EInstallComplete);
       
   282 	SimulatePowerFailureL(EFailInstallComplete, EAfterJournal, KNullDesC);
       
   283 	
       
   284 	DeleteFilesL(*iJournal, EBackupFile);
       
   285 	
       
   286 	SimulatePowerFailureL(EFailBackupFilesRemoved, EBeforeJournal, KNullDesC);
       
   287 	iJournal->WriteJournalEventL(EBackupFilesRemoved);
       
   288 	SimulatePowerFailureL(EFailBackupFilesRemoved, EAfterJournal, KNullDesC);
       
   289 	
       
   290 	DeleteFilesL(*iJournal, ETempFile);
       
   291 	
       
   292 	SimulatePowerFailureL(EFailTempFilesRemoved, EBeforeJournal, KNullDesC);
       
   293 	iJournal->WriteJournalEventL(ETempFilesRemoved);
       
   294 	SimulatePowerFailureL(EFailTempFilesRemoved, EAfterJournal, KNullDesC);
       
   295 	
       
   296 	iJournal->FinishCommitL();
       
   297 	}
       
   298 
       
   299 EXPORT_C void CIntegrityServices::RollBackL(TBool aAllTransactions)
       
   300 	{
       
   301 	DEBUG_PRINTF2(_L8("Integrity Services - Rolling Back Session %Ld."), iTransactionID);
       
   302 
       
   303 	if (aAllTransactions)
       
   304 		{
       
   305 		// search for and rollback any transaction drive list
       
   306 		TDriveUnit systemDrive(iSystemDrive);
       
   307 		RBuf fileSpec;
       
   308 		fileSpec.CreateL(systemDrive.Name(), KMaxFileName);
       
   309 		CleanupClosePushL(fileSpec);
       
   310 		fileSpec.Append(iJournalPath);
       
   311 		fileSpec.Append(KMatchAny);
       
   312 		fileSpec.Append(KExtDelimiter);
       
   313 		fileSpec.Append(KDriveExt);
       
   314 
       
   315 		RDir dir;
       
   316 		TInt err = dir.Open(iFs, fileSpec, KEntryAttNormal);
       
   317 		if (err == KErrNone)
       
   318 			{
       
   319 			CEntryArray* entryArrayContainer = new (ELeave) CEntryArray;
       
   320 			CleanupStack::PushL(entryArrayContainer);
       
   321 			TEntryArray& entryArray = (*entryArrayContainer)();
       
   322 			err = dir.Read(entryArray);
       
   323 			dir.Close();
       
   324 			if (err != KErrNone && err != KErrEof)
       
   325 				{
       
   326 				User::Leave(err);
       
   327 				}
       
   328 			TInt entryCount = entryArray.Count();
       
   329 			for(TInt index = 0; index < entryCount; ++index)
       
   330 				{
       
   331 				// check that the entry is not a directory
       
   332 				if(!entryArray[index].IsDir())
       
   333 					{
       
   334 					TLex lex(entryArray[index].iName);
       
   335 					TInt64 transactionID;
       
   336 					if(lex.Val(transactionID, EHex) == KErrNone)
       
   337 						{
       
   338 						CJournal* journal = NULL;
       
   339 						TRAP(err, journal = CJournal::NewL(iFs, iLoader, transactionID, iJournalPath));
       
   340 						if(err == KErrNone)
       
   341 							{
       
   342 							CleanupStack::PushL(journal);
       
   343 							// start the recovery, do not let corrupt journals prevent
       
   344 							// recovery of other journals
       
   345 							iStartedJournalRollback = ETrue;
       
   346 							TRAP(err, RollBackJournalL(*journal));
       
   347 							if(err != KErrNone && err != KErrCorrupt)
       
   348 								{
       
   349 								// unexpected error
       
   350 								User::Leave(err);
       
   351 								}
       
   352 							CleanupStack::PopAndDestroy(journal);
       
   353 							}
       
   354 						}
       
   355 					}
       
   356 				}
       
   357 			CleanupStack::PopAndDestroy(entryArrayContainer);
       
   358 			}
       
   359 		else if(err != KErrPathNotFound && err != KErrNotFound && err != KErrNotReady)
       
   360 			{
       
   361 			// unexpected error
       
   362 			User::Leave(err);
       
   363 			}
       
   364 		CleanupStack::PopAndDestroy(&fileSpec);
       
   365 		}
       
   366 	else
       
   367 		{
       
   368 		// rollback only this transaction
       
   369 		TRAPD(err, RollBackJournalL(*iJournal));
       
   370 		if(err != KErrNone && err != KErrPathNotFound && err != KErrNotFound
       
   371 				&& err != KErrNotReady)
       
   372 			{
       
   373 			// unexpected error
       
   374 			User::Leave(err);
       
   375 			}
       
   376 		}
       
   377 	}
       
   378 
       
   379 void CIntegrityServices::RollBackJournalL(CJournal& aJournal)
       
   380 	{
       
   381 	aJournal.SynchL();
       
   382 
       
   383 #ifdef __WINSCW__
       
   384 	// For 2 minutes after initial boot, DLLs are not unloaded. If we are doing a
       
   385 	// rollback, we need to make sure any pending unloadeds are actioned, otherwise a
       
   386 	// previously loaded DLL could cause the rollback to fail on windows (on arm it is legal to
       
   387 	// delete a loaded DLL/EXE, whilst on windows it is not).
       
   388 	RLoader loader;
       
   389 	TInt r = loader.Connect();
       
   390 	if(r == KErrNone)
       
   391 		{
       
   392 		(void)loader.CancelLazyDllUnload();
       
   393 		loader.Close();
       
   394 		}
       
   395 #endif
       
   396 	
       
   397 	for(TInt index = 0; index < aJournal.Drives().Count(); index++)
       
   398 		{
       
   399 		// check to see if this drive has already been completed
       
   400 		if(aJournal.CompletedDrives().Find(aJournal.Drives()[index]) != KErrNotFound)
       
   401 			{
       
   402 			continue;
       
   403 			}
       
   404 			
       
   405 		// only attempt to recover writeable drives that are present
       
   406 		TDriveInfo info;
       
   407 		User::LeaveIfError(iFs.Drive(info, aJournal.Drives()[index]));
       
   408 		if (!(info.iMediaAtt & KMediaAttWriteProtected) && info.iType!=EMediaNotPresent)
       
   409 			{
       
   410 			TRAPD(err, RollBackDriveL(aJournal, aJournal.Drives()[index]));
       
   411 			if(err != KErrNone && err != KErrPathNotFound && err != KErrNotFound
       
   412 				&& err != KErrNotReady)
       
   413 				{
       
   414 				// unexpected error
       
   415 				User::Leave(err);
       
   416 				}
       
   417 			}
       
   418 		}
       
   419 	}
       
   420 
       
   421 void CIntegrityServices::RollBackDriveL(CJournal& aJournal, TInt aDrive)
       
   422 	{
       
   423 	aJournal.StartRollbackL(aDrive);
       
   424 	
       
   425 	DEBUG_PRINTF3(_L8("Integrity Services - Rolling Back drive %d, last event %d."), aDrive, aJournal.LastEvent());
       
   426 	switch (aJournal.LastEvent())
       
   427 		{
       
   428 		// Transaction did not complete, rollback required
       
   429 		case ERemovedFile:
       
   430 		case EBackupFile:
       
   431 		case ETempFile:
       
   432 		case EAddedFile:
       
   433 		case EAddedFilesRemoved:
       
   434 		case ERemovedFilesRestored:
       
   435 			// rollback this individual journal from where it last got to.
       
   436 			switch (aJournal.LastEventL(aDrive))
       
   437 				{
       
   438 			case ERemovedFile:
       
   439 			case EBackupFile:
       
   440 			case ETempFile:
       
   441 			case EAddedFile:
       
   442 				DeleteFilesL(aJournal, EAddedFile, aDrive);
       
   443 				
       
   444 				SimulatePowerFailureL(EFailNewFilesRemoved, EBeforeJournal, KNullDesC);
       
   445 				aJournal.WriteJournalEventL(EAddedFilesRemoved, aDrive);
       
   446 				SimulatePowerFailureL(EFailNewFilesRemoved, EAfterJournal, KNullDesC);
       
   447 				
       
   448 				RestoreFilesL(aJournal, aDrive);
       
   449 				
       
   450 				SimulatePowerFailureL(EFailOldFilesRestored, EBeforeJournal, KNullDesC);
       
   451 				aJournal.WriteJournalEventL(ERemovedFilesRestored, aDrive);
       
   452 				SimulatePowerFailureL(EFailOldFilesRestored, EAfterJournal, KNullDesC);
       
   453 				
       
   454 				DeleteFilesL(aJournal, ETempFile, aDrive);
       
   455 				
       
   456 				SimulatePowerFailureL(EFailTempFilesRemoved, EBeforeJournal, KNullDesC);
       
   457 				aJournal.WriteJournalEventL(ETempFilesRemoved, aDrive);
       
   458 				SimulatePowerFailureL(EFailTempFilesRemoved, EAfterJournal, KNullDesC);
       
   459 				break;
       
   460 			
       
   461 			// Transaction did not complete, rollback did not complete, resume rollback
       
   462 			case EAddedFilesRemoved:
       
   463 				RestoreFilesL(aJournal, aDrive);
       
   464 				
       
   465 				SimulatePowerFailureL(EFailOldFilesRestored, EBeforeJournal, KNullDesC);
       
   466 				aJournal.WriteJournalEventL(ERemovedFilesRestored, aDrive);
       
   467 				SimulatePowerFailureL(EFailOldFilesRestored, EAfterJournal, KNullDesC);
       
   468 				
       
   469 				DeleteFilesL(aJournal, ETempFile, aDrive);
       
   470 				
       
   471 				SimulatePowerFailureL(EFailTempFilesRemoved, EBeforeJournal, KNullDesC);
       
   472 				aJournal.WriteJournalEventL(ETempFilesRemoved, aDrive);
       
   473 				SimulatePowerFailureL(EFailTempFilesRemoved, EAfterJournal, KNullDesC);
       
   474 				break;
       
   475 				
       
   476 			case ERemovedFilesRestored:
       
   477 				DeleteFilesL(aJournal, ETempFile, aDrive);
       
   478 				
       
   479 				SimulatePowerFailureL(EFailTempFilesRemoved, EBeforeJournal, KNullDesC);
       
   480 				aJournal.WriteJournalEventL(ETempFilesRemoved, aDrive);
       
   481 				SimulatePowerFailureL(EFailTempFilesRemoved, EAfterJournal, KNullDesC);
       
   482 				break;
       
   483 			
       
   484 			case ETempFilesRemoved:
       
   485 				break;
       
   486 		
       
   487 			// nothing was done, just delete the journal file
       
   488 			case ENone:
       
   489 				break;
       
   490 		
       
   491 			// Erk! Bad state, bad state!
       
   492 			default:
       
   493 				User::Leave(KErrCorrupt);
       
   494 				break;
       
   495 				}
       
   496 			break;
       
   497 			
       
   498 		// Transaction complete, just need to remove the backup
       
   499 		case EInstallComplete:
       
   500 		case EBackupFilesRemoved:
       
   501 			switch (aJournal.LastEventL(aDrive))
       
   502 				{
       
   503 			// At least one journal had a complete transaction...
       
   504 			// roll forwards all journal files.
       
   505 			case ERemovedFile:
       
   506 			case EBackupFile:
       
   507 			case ETempFile:
       
   508 			case EAddedFile:
       
   509 			case EInstallComplete:
       
   510 				DeleteFilesL(aJournal, EBackupFile, aDrive);
       
   511 			
       
   512 				SimulatePowerFailureL(EFailBackupFilesRemoved, EBeforeJournal, KNullDesC);
       
   513 				aJournal.WriteJournalEventL(EBackupFilesRemoved, aDrive);
       
   514 				SimulatePowerFailureL(EFailBackupFilesRemoved, EAfterJournal, KNullDesC);
       
   515 			
       
   516 				DeleteFilesL(aJournal, ETempFile, aDrive);
       
   517 			
       
   518 				SimulatePowerFailureL(EFailTempFilesRemoved, EBeforeJournal, KNullDesC);
       
   519 				aJournal.WriteJournalEventL(ETempFilesRemoved, aDrive);
       
   520 				SimulatePowerFailureL(EFailTempFilesRemoved, EAfterJournal, KNullDesC);
       
   521 				break;
       
   522 			
       
   523 			case EBackupFilesRemoved:
       
   524 		 		DeleteFilesL(aJournal, ETempFile, aDrive);
       
   525 			
       
   526 				SimulatePowerFailureL(EFailTempFilesRemoved, EBeforeJournal, KNullDesC);
       
   527 				aJournal.WriteJournalEventL(ETempFilesRemoved, aDrive);
       
   528 				SimulatePowerFailureL(EFailTempFilesRemoved, EAfterJournal, KNullDesC);
       
   529 				break;
       
   530 				
       
   531 			case ETempFilesRemoved:
       
   532 				break;
       
   533 		
       
   534 			// nothing was done, just delete the journal file
       
   535 			case ENone:
       
   536 				break;
       
   537 		
       
   538 			// unknown state	
       
   539 			default:
       
   540 				User::Leave(KErrCorrupt);
       
   541 				break;
       
   542 				}
       
   543 			break;
       
   544 			
       
   545 		case ETempFilesRemoved:
       
   546 			break;
       
   547 		
       
   548 		// nothing was done, just delete the journal file
       
   549 		case ENone:
       
   550 			break;
       
   551 		
       
   552 		// unknown state	
       
   553 		default:
       
   554 			User::Leave(KErrCorrupt);
       
   555 			break;
       
   556 		}
       
   557 		
       
   558 	aJournal.FinishRollbackL(aDrive);
       
   559 	}
       
   560 
       
   561 void CIntegrityServices::RestoreFilesL(CJournal& aJournal, TInt aDrive)
       
   562 	{
       
   563 	DEBUG_PRINTF2(_L8("Integrity Services - RestoreFilesL drive = %d"), aDrive);
       
   564 	if (aDrive == -1)
       
   565 		{
       
   566 		// This applies to all journals
       
   567 		aJournal.RestoreFilesL(ERemovedFile, *this, EFailRestoringFile);
       
   568 		}
       
   569 	else
       
   570 		{
       
   571 		// specific drive version
       
   572 		aJournal.RestoreFilesL(ERemovedFile, aDrive, *this, EFailRestoringFile);
       
   573 		}
       
   574 	}
       
   575 
       
   576 void CIntegrityServices::DeleteFilesL(CJournal& aJournal, TIntegrityServicesEvent aEvent, TInt aDrive)
       
   577 	{
       
   578 	DEBUG_PRINTF3(_L8("Integrity Services - Delete Files drive = %d, event = %d"), aDrive, aEvent);
       
   579 	if (aDrive == -1)
       
   580 		{
       
   581 		// This applies to all journals
       
   582 		aJournal.DeleteFilesL(aEvent, *this, EFailDeletingFile);
       
   583 		}
       
   584 	else
       
   585 		{
       
   586 		// specific drive version
       
   587 		aJournal.DeleteFilesL(aEvent, aDrive, *this, EFailDeletingFile);
       
   588 		}
       
   589 	}