Added showdebug command.
Also:
* Added an exported constructor to RChildProcess so the iProcess handle was set to zero on construction.
* Fixed bug in fshell_builddocs script that created HTML relative links with backslashes instead of forward slashes.
// cloggerconfig.cpp
//
// Copyright (c) 2007 - 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/ioutils.h>
#include <fshell/clogger.h>
#include <BADESCA.H>
#include <e32msgqueue.h>
using namespace IoUtils;
class CCmdCloggerConfig : public CCommandBase
{
public:
static CCommandBase* NewLC();
~CCmdCloggerConfig();
private:
CCmdCloggerConfig();
void PrintLogL();
void GetBackupFileNameL(TFileName& aName);
void SetAllL(TBool aEnabled);
private: // From CCommandBase.
virtual const TDesC& Name() const;
virtual void DoRunL();
virtual void ArgumentsL(RCommandArgumentList& aArguments);
virtual void OptionsL(RCommandOptionList& aOptions);
private:
RClogger iClogger;
RCloggerLogConsumer iLogGetter;
TUint iGlobalOptions;
TBool iPersist;
TBool iReset;
HBufC* iTagName;
TUint iEnabledMask;
TUint iRotateOptions;
TBool iRotate;
TBool iFollow;
TBool iWipe;
TInt iNumBuffers;
TInt iBufferSize;
RBuf iTempBuffer;
TBool iRdebug;
TBool iBackup;
TBool iRestore;
TBool iDisableAll;
TBool iEnableAll;
};
CCommandBase* CCmdCloggerConfig::NewLC()
{
CCmdCloggerConfig* self = new(ELeave) CCmdCloggerConfig();
CleanupStack::PushL(self);
self->BaseConstructL();
return self;
}
CCmdCloggerConfig::~CCmdCloggerConfig()
{
iClogger.Close();
iLogGetter.Close();
delete iTagName;
iTempBuffer.Close();
}
CCmdCloggerConfig::CCmdCloggerConfig()
{
}
const TDesC& CCmdCloggerConfig::Name() const
{
_LIT(KName, "cloggerconfig");
return KName;
}
#define WRITEIF(opt, flag) if (opt & (RClogger :: flag)) { Write(_L(#flag)); Write(_L(" ")); }
void CCmdCloggerConfig::DoRunL()
{
if (iEnableAll && iDisableAll)
{
LeaveIfErr(KErrArgument, _L("Can't enable and disable all tags"));
}
User::LeaveIfError(iClogger.Connect());
TBool listSettings = ETrue;
if (iReset)
{
iClogger.ResetSettings();
listSettings = EFalse;
}
if (iOptions.IsPresent(&iGlobalOptions))
{
iClogger.SetGlobalOptions(iGlobalOptions);
listSettings = EFalse;
}
if (iOptions.IsPresent(&iRotateOptions))
{
TInt n;
iClogger.GetRotateBehaviour(&n);
iClogger.SetRotateBehaviour(n, iRotateOptions);
listSettings = EFalse;
}
if (iNumBuffers || iBufferSize)
{
if (iNumBuffers == 0)
{
// Need to read it in as we have to set both at once. Bad API...
iClogger.GetRamBufferSize(&iNumBuffers);
}
if (iBufferSize == 0)
{
// Same reason as above
iBufferSize = iClogger.GetRamBufferSize(NULL);
}
iClogger.SetRamBufferSize(iBufferSize, iNumBuffers);
listSettings = EFalse;
}
if (iPersist || iBackup || iRestore)
{
// We don't do anything here, we take action at the end of this function
listSettings = EFalse;
}
if (iRotate)
{
TFileName name;
TInt err = iClogger.Rotate(name);
Printf(_L("Log rotated to %S\r\n"), &name);
if (err) PrintError(err, _L("Rotate returned error"));
listSettings = EFalse;
}
else if (iWipe)
{
TInt oldLogs;
TUint rotopt = iClogger.GetRotateBehaviour(&oldLogs);
iClogger.SetRotateBehaviour(KMaxTInt, RClogger::EDoNothingSpecial); // Change rotate behaviour temporarily
TFileName name;
TInt err = iClogger.Rotate(name);
//Printf(_L("Log rotated to %S\r\n"), &name);
if (err) PrintError(err, _L("Rotate returned error"));
else
{
err = FsL().Delete(name);
iClogger.SetRotateBehaviour(oldLogs, rotopt); // Restore old behaviour
LeaveIfErr(err, _L("Couldn't remove wiped log %S"), &name);
}
listSettings = EFalse;
}
if (iDisableAll)
{
SetAllL(EFalse);
listSettings = EFalse;
}
if (iEnableAll)
{
SetAllL(ETrue);
listSettings = EFalse;
}
if (iRdebug)
{
TUint opts = iClogger.GetGlobalOptions();
opts |= RClogger::ERedirectRDebugPrintToClogger;
iClogger.SetGlobalOptions(opts);
PrintLogL();
}
if (iFollow)
{
PrintLogL(); // Does not return
}
if (iArguments.IsPresent(1))
{
// Set
TInt err = iClogger.SetEnabled(*iTagName, iEnabledMask);
if (err == KErrNotFound)
{
PrintError(err, _L("Tag does not exist, couldn't set it. (NOTE: This behaviour will be changed in the future so you can set tags that haven't been created yet!)"));
User::Leave(KErrNotFound);
}
LeaveIfErr(err, _L("Couldn't enable tag."));
listSettings = EFalse;
}
else if (iArguments.IsPresent(0))
{
// Get
TUint32 e = iClogger.IsEnabled(*iTagName);
Printf(_L("Tag [%S] enabled: 0x%x\r\n"), iTagName, e);
listSettings = EFalse;
}
if (listSettings)
{
// List global options
TUint globalOptions = iClogger.GetGlobalOptions();
Printf(_L("Global options: 0x%x ( "), globalOptions);
if (!globalOptions)
{
Write(_L("None "));
}
else
{
WRITEIF(globalOptions, EBufferLog);
WRITEIF(globalOptions, EMirrorToRDebugPrint);
WRITEIF(globalOptions, EMirrorToBluetooth);
WRITEIF(globalOptions, EMirrorToMessageQueue);
WRITEIF(globalOptions, ERedirectRDebugPrintToClogger);
WRITEIF(globalOptions, EDisableFileWriter);
}
Write(_L(")\r\n"));
// List rotate options
TInt numLogs = 0;
TUint rotateBehaviour = iClogger.GetRotateBehaviour(&numLogs);
Printf(_L("Number of rotated logs to keep: %i\r\n"), numLogs);
Printf(_L("Rotate behaviour: 0x%x ( "), rotateBehaviour);
if (!rotateBehaviour)
{
Write(_L("EDoNothingSpecial "));
}
else
{
WRITEIF(rotateBehaviour, ECopyRotatedToExternalMedia);
WRITEIF(rotateBehaviour, EAutoRotateAtStartup);
WRITEIF(rotateBehaviour, ECompressRotatedLogs);
}
Write(_L(")\r\n"));
// List buffer size
TInt numBuffers = 0;
TInt bufSize = iClogger.GetRamBufferSize(&numBuffers);
Printf(_L("Number of RAM buffers: %i\r\n"), numBuffers);
Printf(_L("Size of RAM buffers: %i\r\n"), bufSize);
// List tags
CDesC16Array* tags = NULL;
RBuf8 enabled;
iClogger.GetTagStatesL(tags, enabled);
TInt count = enabled.Size() / 4;
if (count) Printf(_L("\r\n"));
for (TInt i = 0; i < count; i++)
{
TPtrC tag = tags->operator[](i);
TUint32 e = ((TUint32*)enabled.Ptr())[i];
Printf(_L("Tag [%S] enabled: 0x%x\r\n"), &tag, e);
}
delete tags;
enabled.Close();
}
if (iPersist)
{
iClogger.PersistSettings();
}
if (iBackup)
{
// Args should be: --exec 'cp -ro C:\Private\10202be9\persists\10272efd.cre E:\Private\10202be9\persists\10272efd.cre'
TFileName args;
GetBackupFileNameL(args);
TInt len = args.Length();
args.Append(args);
args.Append('\'');
args[0] = 'C';
args.Insert(len, _L(" "));
args.Insert(0, _L("--exec 'cp -ro "));
RChildProcess shell;
shell.CreateL(_L("fshell.exe"), args, IoSession(), Stdin(), Stdout(), Stderr());
CleanupClosePushL(shell);
TRequestStatus stat;
shell.Run(stat);
User::WaitForRequest(stat);
LeaveIfErr(stat.Int(), _L("Failed to copy cenrep file"));
CleanupStack::PopAndDestroy(&shell);
const TPtrC name = args.Right(len+1);
Printf(_L("Settings backed up to '%S, use --restore option to restore.\r\n"), &name);
}
else if (iRestore)
{
TFileName args;
GetBackupFileNameL(args);
TInt len = args.Length();
//TEntry e;
//LeaveIfErr(FsL().Entry(args, e), _L("No backup file found"));
// Args should be: --exec 'cp E:\Private\10202be9\persists\10272efd.cre C:\Private\10202be9\persists\10272efd.cre'
args.Append(args);
args.Append('\'');
args[len] = 'C';
args.Insert(len, _L(" "));
args.Insert(0, _L("--exec 'cp -ro "));
RChildProcess shell;
shell.CreateL(_L("fshell.exe"), args, IoSession(), Stdin(), Stdout(), Stderr());
CleanupClosePushL(shell);
TRequestStatus stat;
shell.Run(stat);
User::WaitForRequest(stat);
LeaveIfErr(stat.Int(), _L("Failed to copy cenrep file"));
CleanupStack::PopAndDestroy(&shell);
Printf(_L("Settings restored. You must reboot or restart cloggerserver to get the new settings\r\n"));
}
}
void CCmdCloggerConfig::ArgumentsL(RCommandArgumentList& aArguments)
{
aArguments.AppendStringL(iTagName, _L("tag_name"));
aArguments.AppendUintL(iEnabledMask, _L("enabled_mask"));
}
void CCmdCloggerConfig::OptionsL(RCommandOptionList& aOptions)
{
aOptions.AppendUintL(iGlobalOptions, _L("set-global"));
aOptions.AppendBoolL(iPersist, _L("persist"));
aOptions.AppendBoolL(iReset, _L("reset"));
aOptions.AppendUintL(iRotateOptions, _L("set-rotate"));
aOptions.AppendBoolL(iRotate, _L("rotate"));
aOptions.AppendBoolL(iFollow, _L("follow"));
aOptions.AppendIntL(iNumBuffers, _L("num-buffers"));
aOptions.AppendUintL((TUint&)iBufferSize, _L("buffer-size"));
aOptions.AppendBoolL(iWipe, _L("wipe"));
aOptions.AppendBoolL(iRdebug, _L("rdebug"));
aOptions.AppendBoolL(iBackup, _L("backup"));
aOptions.AppendBoolL(iRestore, _L("restore"));
aOptions.AppendBoolL(iDisableAll, _L("disable-all"));
aOptions.AppendBoolL(iEnableAll, _L("enable-all"));
}
EXE_BOILER_PLATE(CCmdCloggerConfig)
void CCmdCloggerConfig::PrintLogL()
{
// Because of how RCloggerLogConsumer API works we can only 'see' things in the clogger ChunkForBufs. This however
// won't be where the descriptor being logged will be unless buffered logging is enabled. To fix properly,
// the rdebug chunk would need to be mapped into the client, and also the Server's iSessionTempBuf and
// CDebugRouterClient's iTempBuf would need to be moved to an accessible chunk
TUint opts = iClogger.GetGlobalOptions();
opts |= RClogger::EBufferLog;
iClogger.SetGlobalOptions(opts);
LeaveIfErr(iLogGetter.Connect(), _L("Couldn't connect to RCloggerLogConsumer"));
iTempBuffer.CreateL(2048);
TRequestStatus stat;
TPtrC8 logLine;
while (ETrue)
{
iLogGetter.GetNextLog(stat, logLine);
User::WaitForRequest(stat);
LeaveIfErr(stat.Int(), _L("GetNextLog returned error"));
// CCommandBase::Write doesn't take 8-bit descriptor so write in iTempBuffer-sized chunks
TPtrC8 lineFrag(logLine);
const TInt buflen = iTempBuffer.MaxLength();
while (lineFrag.Length())
{
TPtrC8 frag = lineFrag.Left(buflen);
iTempBuffer.Copy(frag);
//HexDumpL(frag, iTempBuffer);
TInt err = Stdout().Write(iTempBuffer);
LeaveIfErr(err, _L("Write of %d bytes (%d total) failed"), iTempBuffer.Length(), logLine.Length());
lineFrag.Set(lineFrag.Mid(frag.Length()));
}
}
}
void CCmdCloggerConfig::GetBackupFileNameL(TFileName& aName)
{
TInt err = KErrNone;
TInt theDrive = KErrNotFound;
// Figure out the first external media device
for (TInt drive = EDriveA; drive <= EDriveZ; drive++)
{
TVolumeInfo info;
err = FsL().Volume(info, drive);
if (err == KErrNone)
{
//LogNote(ELogDisks, _L8("Found drive %c iDrivaAtt=0x%x iType=0x%x"), 'A' + drive, info.iDrive.iDriveAtt, info.iDrive.iType);
}
if (err == KErrNone && ((info.iDrive.iDriveAtt & KDriveAttRemovable) || info.iDrive.iType == EMediaHardDisk)) // Added the check for hard disk so we can use _epoc_drive_d in the emulator
{
// Found one
theDrive = drive;
break;
}
}
LeaveIfErr(theDrive, _L("Couldn't find a removable drive to backup on to"));
aName = _L("?:\\private\\10202be9\\persists\\10272efd.cre");
TChar c;
Fs().DriveToChar(theDrive, c);
aName[0] = c;
}
void CCmdCloggerConfig::SetAllL(TBool aEnabled)
{
CDesC16Array* tags = NULL;
RBuf8 states;
CleanupClosePushL(states);
iClogger.GetTagStatesL(tags, states);
CleanupStack::PushL(tags);
if (aEnabled)
{
states.Fill(TChar(0xff));
}
else
{
states.FillZ();
}
iClogger.SetTagStatesL(tags, states);
CleanupStack::PopAndDestroy(2, &states);
}