Implemented RObjectIx-based memoryaccess APIs.
Upshot is that objinfo now works again on platforms that define FSHELL_NO_DOBJECTIX_SUPPORT.
// 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;
}