commands/ffstrace/ffstraceplugin.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Thu, 26 Aug 2010 00:49:35 +0100
changeset 45 534b01198c2d
parent 0 7f656887cf89
permissions -rw-r--r--
Added ENotifyKeypresses and ECaptureCtrlC flags to CCommandBase. Commands can now get keypresses and handle ctrl-C via callbacks instead of having to implement custom active objects. As part of this extended the CCommandBase extension interface to MCommandExtensionsV2 for the new virtual functions KeyPressed(TUint aKeyCode, TUint aModifiers) and CtrlCPressed(). sudo now cleans up correctly by using ECaptureCtrlC.

// ffstraceplugin.cpp
// 
// Copyright (c) 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 <fshell/extrabtrace.h>
#include <f32plugin.h>
#include <f32pluginutils.h>
#include <fshell/ltkutils.h>

//#define LOG_FUNC() RDebug::Printf(__PRETTY_FUNCTION__)
//#define LOG(args...) RDebug::Printf(args)
//#define LOGW(args...) RDebug::Print(args)
#define LOG_FUNC()
#define LOG(args...)
#define LOGW(args...)


NONSHARABLE_CLASS(CFfsTracerPluginFactory) : public CFsPluginFactory
	{
public:
	static CFfsTracerPluginFactory* NewL();

	// from CFsPluginFactory
	virtual TInt Install();
	virtual CFsPlugin* NewPluginL();
	virtual TInt UniquePosition();

private:
	CFfsTracerPluginFactory();
	};

NONSHARABLE_CLASS(CFfsTracerFsPlugin) : public CFsPlugin
	{
public:
	static CFfsTracerFsPlugin* NewL();
	virtual ~CFfsTracerFsPlugin();
	
	// from CFsPlugin
	virtual void InitialiseL();
	TInt SessionDisconnect(CSessionFs* aSession);
	virtual TInt DoRequestL(TFsPluginRequest& aRequest);
	virtual CFsPluginConn* NewPluginConnL();
private:
	CFfsTracerFsPlugin();
	};
	
class CFfsTracerFsPluginConn : public CFsPluginConn
	{
public:
	CFfsTracerFsPluginConn();

	// from CFsPluginConn
	virtual TInt DoControl(CFsPluginConnRequest& aRequest);
	virtual void DoRequest(CFsPluginConnRequest& aRequest);
	virtual void DoCancel(TInt aReqMask);
	};

extern "C" EXPORT_C CFsPluginFactory* CreateFileSystem()
	{
	return CFfsTracerPluginFactory::NewL();
	}

CFfsTracerPluginFactory* CFfsTracerPluginFactory::NewL()
	{
	return(new(ELeave) CFfsTracerPluginFactory());
	}

CFfsTracerPluginFactory::CFfsTracerPluginFactory()
	{
	}

_LIT(KFfsTracerPluginName, "FfsTracePlugin");

TInt CFfsTracerPluginFactory::Install()
	{
	LOG_FUNC();
	iSupportedDrives = 0x7FFFFFF; // KPluginSupportAllDrives | KPluginVersionTwo. Not specified symbolically to be compatible with fileservers that didn't support v2 plugins
	
	TInt err;
	err = SetName(&KFfsTracerPluginName);
	LOG(" returned %d", err);
	return err;
	}

CFsPlugin* CFfsTracerPluginFactory::NewPluginL()
	{
	return CFfsTracerFsPlugin::NewL();
	}
	
TInt CFfsTracerPluginFactory::UniquePosition()
	{
	return 1; // Isn't used, apparently
	}

//

CFfsTracerFsPluginConn::CFfsTracerFsPluginConn()
	{
	}

TInt CFfsTracerFsPluginConn::DoControl(CFsPluginConnRequest& /*aRequest*/)
	{
	return KErrNone;
	}

void CFfsTracerFsPluginConn::DoRequest(CFsPluginConnRequest& /*aRequest*/)
	{
	}

void CFfsTracerFsPluginConn::DoCancel(TInt /*aReqMask*/)
	{
	}

//

CFfsTracerFsPlugin* CFfsTracerFsPlugin::NewL()
	{
	return new(ELeave) CFfsTracerFsPlugin();
	}
	
CFfsTracerFsPlugin::CFfsTracerFsPlugin()
	{
	LOG_FUNC();
	}

static const TFsMessage KMessages[] =
	{
	EFsDelete,
	EFsRename,
	EFsReplace,
	EFsEntry,
	EFsFileSubClose,
	EFsFileOpen,
	EFsFileCreate,
	EFsFileReplace,
	EFsFileTemp,
	EFsFileRename,
	};
static const TInt KMessageCount = sizeof(KMessages) / sizeof(TFsMessage);

CFfsTracerFsPlugin::~CFfsTracerFsPlugin()
	{
	LOG_FUNC();
	for (TInt i = 0; i < KMessageCount; i++)
		{
		UnregisterIntercept(KMessages[i], CFsPlugin::EPrePostIntercept);
		}
	}

void CFfsTracerFsPlugin::InitialiseL()
	{
	// intercept all calls at start
	for (TInt i = 0; i < KMessageCount; i++)
		{
		RegisterIntercept(KMessages[i], CFsPlugin::EPrePostIntercept);
		}
	}

TInt CFfsTracerFsPlugin::SessionDisconnect(CSessionFs* /*aSession*/)
	{
	// CSessionFs is a private class! It's in the main file server and 
	// has no exported methods!  What's the use of passing it here?
	return KErrNone;
	}

CFsPluginConn* CFfsTracerFsPlugin::NewPluginConnL()
	{
	LOG_FUNC();
	return new(ELeave) CFfsTracerFsPluginConn();
	}

TInt CFfsTracerFsPlugin::DoRequestL(TFsPluginRequest& aRequest)
	{
	// This is where it all happens
	
	TInt subcat = 0;
	TInt fn = aRequest.Function();
	// Map from FS opcodes to the compacted btrace ones
	switch (fn)
		{
		case EFsDelete: subcat = BTrace::EFfsDelete; break;
		case EFsRename: subcat = BTrace::EFfsRename; break;
		case EFsReplace: subcat = BTrace::EFfsReplace; break;
		case EFsEntry: subcat = BTrace::EFfsEntry; break;
		case EFsFileSubClose: subcat = BTrace::EFfsFileSubClose; break;
		case EFsFileOpen: subcat = BTrace::EFfsFileOpen; break;
		case EFsFileCreate: subcat = BTrace::EFfsFileCreate; break;
		case EFsFileReplace: subcat = BTrace::EFfsFileReplace; break;
		case EFsFileTemp: subcat = BTrace::EFfsFileTemp; break;
		case EFsFileRename: subcat = BTrace::EFfsFileRename; break;
		default:
			// An operation we're not interested in
			return KErrNone;
		}
	if (aRequest.IsPostOperation()) subcat |= BTrace::EFfsPost;

	TBuf<513> name; // Twice as big as a max filename because for renames we need it to fit two TFileNames
	GetName(&aRequest, name);

	if (fn == EFsRename || fn == EFsFileRename)
		{
		name.Append(TChar(0));
		TPtr newName((TUint16*)(name.Ptr() + name.Length()), 0, name.MaxLength() - name.Length());
		GetNewName(&aRequest, newName);
		LOGW(_L("new name is %S"), &newName);
		name.SetLength(name.Length() + newName.Length());
		}

	// Only try to use request.Message() if it's a valid handle
	TUint threadId = 0xFFFFFFFFu;
	if(aRequest.Message().Handle() != KNullHandle)
		{
		RThread clientThread;
		aRequest.Message().Client(clientThread, EOwnerThread);
		threadId = clientThread.Id();
		clientThread.Close();
		}

	BTraceBig(BTrace::EFfsTrace, subcat, threadId, name.Ptr(), name.Size());
	
	return KErrNone;
	}