installationservices/swtransactionservices/source/server/integrityservices.cpp
branchRCL_3
changeset 26 8b7f4e561641
parent 25 7333d7932ef7
child 27 e8965914fac7
--- a/installationservices/swtransactionservices/source/server/integrityservices.cpp	Tue Aug 31 15:21:33 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,381 +0,0 @@
-/*
-* Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "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: 
-* CIntegrityServices implementation
-*
-*/
-
-
-/**
- @file 
- @released
- @internalTechnology
-*/
-
-#include "integrityservices.h"
-#include "journal.h"
-#include "operationfunctions.h"
-#include "usiflog.h"
-
-#include <f32file.h>
-
-using namespace Usif;
-
-_LIT(KTransactionPath, "\\sys\\install\\integrityservices\\");
-
-CIntegrityServices::TFailType CIntegrityServices::iFailType = EFailNone;
-CIntegrityServices::TFailPosition CIntegrityServices::iFailPosition = EBeforeJournal;
-TFileName CIntegrityServices::iFailFileName;
-TBool CIntegrityServices::iIsFailureTestingEnabled = EFalse;
-
-
-/**
- * This is a trivial C class that just encapsulates a TEntryArray object in order to 
- * facilitate its storage on the heap.
- *
- * @released
- * @internalComponent 
- */
-class CEntryArray : public CBase
-	{
-public:
-	inline TEntryArray& operator()();
-
-private:
-	/**
-	 * Container to hold file entries
-	 */
-	TEntryArray iEntryArray;
-	};
-
-inline TEntryArray& CEntryArray::operator()()
-	{
-	return iEntryArray;
-	}
-
- CIntegrityServices* CIntegrityServices::NewL(TStsTransactionId aTransactionID)
-	{
-	CIntegrityServices* self = CIntegrityServices::NewLC(aTransactionID);
-	CleanupStack::Pop(self);
-	return self;
-	}
-
- CIntegrityServices* CIntegrityServices::NewLC(TStsTransactionId aTransactionID)
-	{
-	CIntegrityServices* self = new(ELeave) CIntegrityServices(aTransactionID);
-	CleanupStack::PushL(self);
-	self->ConstructL();
-	return self;
-	}
-
- CIntegrityServices::CIntegrityServices(TStsTransactionId aTransactionID) : iTransactionID(aTransactionID)
-	{
-	}
-
- CIntegrityServices::~CIntegrityServices()
-	{
-	delete iJournal;
-	iFs.Close();
-	
-	iLoader.Close();
-	}
-
- void CIntegrityServices::ConstructL()
-	{
-	DEBUG_PRINTF2(_L("CIntegrityServices::ConstructL() - Opening session with  Session ID %X."), iTransactionID);
-	
-	User::LeaveIfError(iFs.Connect());
-	User::LeaveIfError(iFs.ShareProtected()); //needed as new RFiles are to be passed back to client's side
-	User::LeaveIfError(iLoader.Connect());
-
-	// store the journal path and create the journal
-	TParsePtrC pathPtr(KTransactionPath);
-	iJournalPath = pathPtr.Path();
-	iJournal = CJournal::NewL(iFs, iLoader, iTransactionID, iJournalPath);
-	iSystemDrive = ::RFs::GetSystemDrive();
-	}
- 
-const TInt KIntegrityServicesSimulatedBatteryFailure=-10205; 
- 
-/*static*/ void CIntegrityServices::SimulatePowerFailureL(TFailType aFailType, TFailPosition aFailPosition, const TDesC& aFailFileName)
-	{
-	if (!iIsFailureTestingEnabled)
-		return;
-	
-	if(iFailType == aFailType && iFailPosition == aFailPosition && iFailFileName == aFailFileName)
-		{
-		User::Leave(KIntegrityServicesSimulatedBatteryFailure);
-		}
-	}
-
-/*static*/ void CIntegrityServices::NormalizeDirectoryName(TDes& aFileName)
-{
-	// Directories are represented in the integrity tree and integrity journal exactly as files,
-	// without the trailing slash 
-	TInt lastCharPos = aFileName.Length() - 1;
-	if ( lastCharPos >= 0 && aFileName[lastCharPos] == KPathDelimiter &&
-		 aFileName.Locate(KPathDelimiter) != lastCharPos) // Take care not to remove slash from "c:\" and the like
-		{
-		aFileName.Delete(lastCharPos, 1);
-		}			
-}
-
- void CIntegrityServices::RegisterNewL(const TDesC& aFileName)
-	{
-	DEBUG_PRINTF3(_L("CIntegrityServices::RegisterNewL() - Session %X, File: %S."),	iTransactionID, &aFileName);
-
-	HBufC* localFilenameHeap = aFileName.AllocLC();
-	TPtr localFilename = localFilenameHeap->Des();
-	NormalizeDirectoryName(localFilename); // If it is a directory name, make sure to normalize it
-		
-	// Record the added file or directory in the journal
-	SimulatePowerFailureL(EFailAddingNewFile, EBeforeJournal, aFileName);
-	iJournal->AddL(localFilename);
-	SimulatePowerFailureL(EFailAddingNewFile, EAfterJournal, aFileName);
-	CleanupStack::PopAndDestroy(localFilenameHeap);
-	}
-
- void VerifyMkDirErrorL(TInt err)
-	{
-	if(err != KErrNone && err != KErrAlreadyExists)
-		{
-		User::Leave(err);
-		}	
-	}
- 
- void ProcessNewFileRegistrationResultL(TInt err, RFs& aFs, const TDesC& aFileName, RFile& aFile)
-	{
-	if(err!= KErrNone)
-		{
-		//if we hit this point it means we successfully created the new file however registering with the transaction has  failed
-		//so we have to remove the new file to make the journal and the file system consistent
-		aFile.Close();
-		aFs.Delete(aFileName);
-		User::Leave(err);
-		}	
-	}
-
- void CIntegrityServices::CreateNewL(const TDesC& aFileName, RFile &newFile, TUint aFileMode)
-	{
-	DEBUG_PRINTF3(_L("CIntegrityServices::CreateNewL() - Session %X, File: %S."),	iTransactionID, &aFileName);
-	TInt err = iFs.MkDirAll(aFileName); //first we have to create the full directory path to aFileName otherwise RFs::Create will fail
-	VerifyMkDirErrorL(err);
-	User::LeaveIfError(newFile.Create(iFs, aFileName, aFileMode));
-	TRAPD(regResult, RegisterNewL(aFileName));	
-	ProcessNewFileRegistrationResultL(regResult, iFs, aFileName, newFile); //checks if the registration failed and cleans up the file in the filesystem if it did
-	}
-
- void CIntegrityServices::RemoveL(const TDesC& aFileName)
-	{
-	DEBUG_PRINTF3(_L("CIntegrityServices::RemoveL() - Session %X, File: %S."), iTransactionID, &aFileName);
-
-	// before doing anything check that the file or directory exists
-	TEntry entry;
-	
-	TInt res = iFs.Entry(aFileName, entry);
-	if (res == KErrNotFound || res == KErrPathNotFound)
-		return; // If the file is not present, do nothing. Returning an error would require the user of the API to do additional checks
-	User::LeaveIfError(res);
-
-	// We might need to grow this buffer by one byte later
-	HBufC* localFilenameHeap = HBufC::NewLC(aFileName.Length() + 1);
-	TPtr localFilename = localFilenameHeap->Des();
-	localFilename.Copy(aFileName);
-	
-	TBool isFilenameDir = entry.IsDir();
-	// The "if" below is not functionally necessary, but it is a slight optimization - 
-	// so that we won't attempt to normalize directory name on files. The optimization is not
-	// 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
-	if ( isFilenameDir ) 
-		{
-		NormalizeDirectoryName(localFilename);
-		}
-
-	RBuf backupFileName;
-	backupFileName.CreateL(KMaxFileName);
-	CleanupClosePushL(backupFileName);
-	SimulatePowerFailureL(EFailRemovingFile, EBeforeJournal, aFileName);
-	iJournal->RemoveL(localFilename, backupFileName);
-		
-	if (backupFileName.Length())
-		{
-		SimulatePowerFailureL(EFailRemovingFile, EAfterJournal, aFileName);
-
-		TInt err = iFs.MkDirAll(backupFileName);
-		VerifyMkDirErrorL(err);
-
-		SimulatePowerFailureL(EFailRemovingFile, EBeforeAction, aFileName);
-			err = iFs.Rename(localFilename, backupFileName);
-			DEBUG_PRINTF4(_L("CIntegrityServices::RemoveL() - Renamed %S as %S error %d"), &localFilename, &backupFileName, err);
-			User::LeaveIfError(err);
-		SimulatePowerFailureL(EFailRemovingFile, EAfterAction, aFileName);
-		}
-	else
-		{
-		DEBUG_PRINTF2(_L("CIntegrityServices::RemoveL() - %S already backed up"), &aFileName);
-		SimulatePowerFailureL(EFailRemovingFile, EBeforeAction, aFileName);
-		// If backupFileName is zero-length, the file was added earlier
-		// in the same journal and doesn't need to be backed up.
-		if (isFilenameDir)
-			{
-			CFileMan* fileman = CFileMan::NewL(iFs);
-			CleanupStack::PushL(fileman);			
-			// Make sure to append slash before calling RmDir - otherwise it deletes the parent directory
-			if (localFilename[localFilename.Length()-1] != KPathDelimiter)
-	  			{
-  				localFilename.Append(KPathDelimiter);
-  				}			
-			User::LeaveIfError(fileman->RmDir(localFilename)); // A directory cannot be a paged exec., so we don't have to use iLoader
-			CleanupStack::PopAndDestroy(fileman);
-			}
-		else
-			{
-			User::LeaveIfError(iLoader.Delete(aFileName));
-			}
-		SimulatePowerFailureL(EFailRemovingFile, EAfterAction, aFileName);			
-		}
-
-	// Don't leave an empty directory structure, try pruning it
-	RemoveDirectoryTreeL(iFs, aFileName);
-
-	CleanupStack::PopAndDestroy(2, localFilenameHeap); // backupFileName
-	}
-
- void CIntegrityServices::RegisterTemporaryL(const TDesC& aFileName)
-	{
-	DEBUG_PRINTF3(_L("CIntegrityServices::RegisterTemporaryL() - Session %X, File: %S."), iTransactionID, &aFileName);
-
-	// record the temporary file or directory in the journal
-	SimulatePowerFailureL(EFailAddingTempFile, EBeforeJournal, aFileName);
-	iJournal->TemporaryL(aFileName);
-	SimulatePowerFailureL(EFailAddingTempFile, EAfterJournal, aFileName);
-	}
-
- void CIntegrityServices::CreateTemporaryL(const TDesC& aFileName, RFile &newFile, TUint aFileMode)
-	{
-	DEBUG_PRINTF3(_L("CIntegrityServices::CreateTemporaryL() - Session %X, File: %S."), iTransactionID, &aFileName);
-
-	TInt err = iFs.MkDirAll(aFileName); //first we have to create the full directory path to aFileName otherwise RFs::Create will fail
-	VerifyMkDirErrorL(err);
-	User::LeaveIfError(newFile.Create(iFs, aFileName, aFileMode));
-	TRAPD(regResult, RegisterTemporaryL(aFileName));
-	ProcessNewFileRegistrationResultL(regResult, iFs, aFileName, newFile);
-	}
-
- void CIntegrityServices::OverwriteL(const TDesC& aFileName, RFile &newFile, TUint aFileMode)
-	{
-	DEBUG_PRINTF3(_L("CIntegrityServices::OverwriteL() - Session %X, File: %S."), iTransactionID, &aFileName);
-
-	TBool b;
-	TInt err;
-	if((err=iFs.IsFileOpen(aFileName, b))== KErrNone) //returned error code shows whether the file exists or not; the bool value is ignored
-		{
-		//file exists remove first
-		RemoveL(aFileName);
-		}
-	else
-		{
-		if(err != KErrNotFound)
-			{
-			User::Leave(err);
-			}
-		}
-	CreateNewL(aFileName, newFile, aFileMode);
-	}
-
- void CIntegrityServices::CommitL()
-	{
-	DEBUG_PRINTF2(_L("CIntegrityServices::CommitL() - Session %X."), iTransactionID);	
-	iJournal->CommitL();
-	}
-
- void CIntegrityServices::RollBackL(TBool aRecordAllRollbackEvents /* = ETrue */)
-	{
-	DEBUG_PRINTF2(_L("CIntegrityServices::RollBackL() - transaction %X"), iTransactionID);
-	iJournal->RollBackL(aRecordAllRollbackEvents);
-	}
-
-/*static*/ void CIntegrityServices::GetListOfTransactionsL(RArray<TStsTransactionId>& aIdArray)
-	{
-	RFs fs;
-	User::LeaveIfError(fs.Connect());
-	CleanupClosePushL(fs);
-	TDriveUnit systemDrive(::RFs::GetSystemDrive());
-	RBuf fileSpec;
-	fileSpec.CreateL(systemDrive.Name(), KMaxFileName);
-	CleanupClosePushL(fileSpec);
-	fileSpec.Append(KTransactionPath);
-	fileSpec.Append(KMatchAny);
-	fileSpec.Append(KExtDelimiter);
-	fileSpec.Append(KDriveExt);
-
-	RDir dir;
-	TInt err = dir.Open(fs, fileSpec, KEntryAttNormal);
-	CleanupStack::PopAndDestroy(&fileSpec);
-	if (err == KErrPathNotFound || err == KErrNotFound)
-		{
-		CleanupStack::PopAndDestroy(&fs);
-		return; // These errors are not considered fatal - there may be no journals present
-		}
-	User::LeaveIfError(err);
-	CleanupClosePushL(dir);
-	
-	CEntryArray* entryArrayContainer = new (ELeave) CEntryArray;
-	TEntryArray& entryArray = (*entryArrayContainer)();
-	err = dir.Read(entryArray);
-	CleanupStack::PopAndDestroy(&dir);
-	CleanupStack::PushL(entryArrayContainer);	
-	if (err != KErrNone && err != KErrEof)
-		{
-		User::Leave(err);
-		}
-	TInt entryCount(entryArray.Count());
-	for (TInt index = 0; index < entryCount; ++index)
-		{
-		TStsTransactionId transactionID;
-		if (CJournal::RecoverTransactionIdFromDrvFileName(
-				entryArray[index].iName, transactionID) == KErrNone)
-			{
-			aIdArray.AppendL(transactionID);
-			}
-		}
-	CleanupStack::PopAndDestroy(entryArrayContainer);
-	CleanupStack::PopAndDestroy(&fs);
-	}
-
-/*static*/ void CIntegrityServices::RollbackAllL()
-	{
-	RArray<TStsTransactionId> transactionIDs;
-	CleanupClosePushL(transactionIDs);
-	CIntegrityServices::GetListOfTransactionsL(transactionIDs);
-	TInt numberOfTransactions(transactionIDs.Count());
-	TInt lastError=KErrNone;
-	DEBUG_PRINTF2(_L("CIntegrityServices::RollbackAllL() %d transactions have been found."), numberOfTransactions );							
-	for(TInt i=0; i<numberOfTransactions; ++i)
-		{
-		DEBUG_PRINTF2(_L("CIntegrityServices::RollbackAllL() Trying to roll back transaction %X"), transactionIDs[i]);
-		TRAPD(err,
-			CIntegrityServices* transactionPtr = CIntegrityServices::NewLC(transactionIDs[i]);
-			transactionPtr->RollBackL(EFalse); // Specify not to record roll back events. If we failed in the middle of a previous roll back, due to lack of resources we shouldn't be trying to record more events
-			CleanupStack::PopAndDestroy(transactionPtr);
-			); //failing to roll back one transaction shouldn't affect the overall rollback all procedure
-		if(err!=KErrNone)
-			{
-			lastError=err; //remember last error and leave with that error code indicating an error in the overall procedure
-			}
-		DEBUG_PRINTF2(_L("CIntegrityServices::RollbackAllL() Rolled back transaction %X"), transactionIDs[i]);			
-		}
-	CleanupStack::PopAndDestroy(&transactionIDs);
-	User::LeaveIfError(lastError);
-	}