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;
}