commands/backup/backup_child.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Sun, 17 Oct 2010 18:43:12 +0100
changeset 69 849a0b46c767
parent 0 7f656887cf89
permissions -rw-r--r--
Fixed lots of issues with installing a low-caps version of fshell from SIS file. * Fixed issue in CCommandFactory whereby some APIs like GetCommandInfoL could trigger allocations on the wrong heap or signals to the wrong thread. The symptoms were often seen as a crash in the which_00 thread when running ciftest. * Lots of build fixes for when FSHELL_PROTECTED_UIDS isn't defined and when all capabilities aren't available. * Added new platform.mmh macro FSHELL_OPEN_SIGNED. * Open signing of fshell SIS files is now supported for production S60 handsets. Build fshell with the FSHELL_OPEN_SIGNED macro defined (and without defining FSHELL_CAP_ALL or FSHELL_PROTECTED_UIDS) in your platform.mmh and submit \epoc32\fshell\fshell.unsigned.sis to https://www.symbiansigned.com/app/page/public/openSignedOnline.do . The following commands are not available when using Open Signing due to Platform Security restrictions: fdb; kerninfo; chunkinfo; svrinfo; objinfo; sudo; fsck; localdrive; ramdefrag; readmem; reboot; setcritical; setpriority. Others such as chkdeps, e32header, ps, and fshell itself will run but in a restricted capacity (for example, fshell will no longer allow you to modify files in the \sys\bin directory). * Removed commands objinfo, svrinfo, chunkinfo, readmem, fsck completely when memory access isn't present - previously they would still appear in the help but would give an error if you tried to run them.

// backup_child.cpp
// 
// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "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:
// Accenture - Initial contribution
//

#include <e32property.h>
#include <connect/sbdefs.h>
#include <baBackup.h>
#include "backup.h"

_LIT(KBackupOp,		"-b");
_LIT(KRestoreOp,	"-r");

const TInt KIdleTime = 5000000; // microseconds

using namespace conn;

class CBackupAO : public CActive
	{
public:
	static CBackupAO* NewL();
	~CBackupAO();
	void Start();
private:
	CBackupAO();
	void ConstructL();
	void CheckForRestoreFlagL();

	// from CActive
	void DoCancel();
	void RunL();
private:
	CBaBackupSessionWrapper* iBackupSession;
	RSemaphore iSem;
	TBool iRestoreOp;
	};


CBackupAO* CBackupAO::NewL()
	{
	CBackupAO* self = new (ELeave) CBackupAO();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CBackupAO::CBackupAO():
CActive(CActive::EPriorityStandard)
	{
	CActiveScheduler::Add(this);
	}

CBackupAO::~CBackupAO()
	{
	Cancel();
	delete iBackupSession; // will also issue the ETakeLock to system apps
	if (iSem.Handle() > 0)
		iSem.Close();
	}

void CBackupAO::ConstructL()
	{
	iBackupSession = CBaBackupSessionWrapper::NewL();
	User::LeaveIfError(iSem.CreateGlobal(KBackupSemaphore, 0, EOwnerProcess));
	CheckForRestoreFlagL();
	}

void CBackupAO::Start()
	{
	iBackupSession->CloseAll(MBackupObserver::EReleaseLockNoAccess, iStatus);
	SetActive();
	}

void CBackupAO::RunL()
	{
	TInt error = iStatus.Int();

	// check which instruction we must send
	conn::TBURPartType instruction = conn::EBURBackupFull;
	if (iRestoreOp)
		instruction = conn::EBURRestoreFull;
	
	// inform subscribed parties of our intentions
	RProperty bk;
	if (error == KErrNone)
		error = bk.Set(KUidSystemCategory, KUidBackupRestoreKey, instruction);
	
	// block for a little while to give apps a chance to process the backup instruction
	User::After(KIdleTime);
	
	// inform fshell's backup cmd we've put the system into backup-mode (or not!)
	RProcess().Rendezvous(error);
	if (error == KErrNone)
		{
		iSem.Wait(); // wait for signal from fshell's backup cmd that we're ok to terminate
		bk.Set(KUidSystemCategory, KUidBackupRestoreKey, conn::EBURNormal); // ignore the error in this case. what else can I do?
		}

	// the process has done it's thing
	CActiveScheduler::Stop();
	}

void CBackupAO::DoCancel()
	{
	ASSERT(iBackupSession);
	iBackupSession->RestartAll();
	}

//
// CBackupAO::CheckForRestoreFlagL
// determine whether we're issuing a backup or a restore
//
void CBackupAO::CheckForRestoreFlagL()
	{
	HBufC *buffer = HBufC::NewL(User::CommandLineLength());
	CleanupStack::PushL(buffer);
	TPtr cmdline = buffer->Des();
	User::CommandLine(cmdline);
	const TInt bPos = cmdline.Find(KBackupOp);
	const TInt rPos = cmdline.Find(KRestoreOp);
	CleanupStack::PopAndDestroy(1);
	if (bPos != KErrNotFound)
		{
		if (rPos != KErrNotFound)
			User::Leave(KErrArgument);
		iRestoreOp = EFalse;
		return;
		}
	if (rPos != KErrNotFound)
		{
		iRestoreOp = ETrue;
		return;
		}
	User::Leave(KErrArgument);
	}


static void RunL()
	{
	// Active Scheduler
	CActiveScheduler* s = new(ELeave) CActiveScheduler;
	CleanupStack::PushL(s);
	CActiveScheduler::Install(s);

	CBackupAO* woop = CBackupAO::NewL();
	CleanupStack::PushL(woop);
	woop->Start();

	// start the active scheduler
	CActiveScheduler::Start();
	CleanupStack::PopAndDestroy(2, s);
	}

// program entry-point
TInt E32Main()
	{
	__UHEAP_MARK;
	CTrapCleanup* cleanup = CTrapCleanup::New();
	TInt err = KErrNoMemory;
	if (cleanup)
		{
		TRAP(err, RunL());
		delete cleanup;
		}
	__UHEAP_MARKEND;
	return err;
	}