Added --no-write to gobble, fixed crash in start --timeout.
Also changed help to output one command per line (instead of columnizing) if not attached to a console. It's the same as what ls does.
// cenrep.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 <centralrepository.h>
#include <fshell/ltkutils.h>
#include <fshell/descriptorutils.h>
using namespace IoUtils;
class CCmdCenrep : public CCommandBase
{
public:
static CCommandBase* NewLC();
~CCmdCenrep();
private:
CCmdCenrep();
void PrintKeyL(TUint aKey, RBuf8& valDes);
template <class KEYTYPE>
void SetKeyL(const KEYTYPE& aVal);
void ListRepositoriesL();
void ForceSetKeyL(TInt aVal);
void ForceSetKeyL(const TDesC& aVal);
void SudoL(TRefByValue<const TDesC> aFmt, ...);
void AddFilesL(RArray<TUint>&, const TDesC& aMatch, const TDesC& aDir);
private: // From CCommandBase.
virtual const TDesC& Name() const;
virtual void DoRunL();
virtual void ArgumentsL(RCommandArgumentList& aArguments);
virtual void OptionsL(RCommandOptionList& aOptions);
private:
// Arguments
TUint iRepository;
TUint iKey;
// Options
HBufC* iStringVal;
TInt iIntVal;
TBool iForce;
TBool iDelete;
TBool iReset;
CRepository* iRep;
};
CCommandBase* CCmdCenrep::NewLC()
{
CCmdCenrep* self = new(ELeave) CCmdCenrep();
CleanupStack::PushL(self);
self->BaseConstructL();
return self;
}
CCmdCenrep::~CCmdCenrep()
{
delete iStringVal;
delete iRep;
}
CCmdCenrep::CCmdCenrep()
{
}
const TDesC& CCmdCenrep::Name() const
{
_LIT(KName, "cenrep");
return KName;
}
void CCmdCenrep::DoRunL()
{
//__DEBUGGER();
if (iRepository == 0)
{
ListRepositoriesL();
return;
}
TRAPD(err, iRep = CRepository::NewL(TUid::Uid(iRepository)));
if (err && iForce)
{
// force create a repository?
}
else
{
if (err == KErrNotFound)
{
PrintError(err, _L("Repository 0x%x not found"), iRepository);
}
User::LeaveIfError(err);
}
if (iDelete)
{
if (!iArguments.IsPresent(1))
{
// Delete all
if (iForce)
{
SudoL(_L("--delete"));
}
else
{
TUint32 errorKey = 0;
err = iRep->Delete(0, 0, errorKey);
if (err && errorKey && errorKey != NCentralRepositoryConstants::KUnspecifiedKey)
{
PrintError(err, _L("Delete failed due to key 0x%x"), errorKey);
}
}
}
else
{
if (iForce)
{
SudoL(_L("--delete %d"), iKey);
}
else
{
err = iRep->Delete(iKey);
}
}
if (err == KErrPermissionDenied)
{
PrintError(err, _L("Delete failed, retry with --force"));
}
User::LeaveIfError(err);
}
else if (iReset)
{
if (iForce)
{
delete iRep;
iRep = NULL;
LtkUtils::RLtkBuf persistsName;
CleanupClosePushL(persistsName);
persistsName.AppendFormatL(_L("C:\\private\\10202be9\\persists\\%08x.cre"), iRepository);
err = FsL().Delete(persistsName);
LeaveIfErr(err, _L("Couldn't delete repository file %S"), &persistsName);
CleanupStack::PopAndDestroy(&persistsName);
}
else
{
User::LeaveIfError(iRep->Reset());
}
}
else if (iOptions.IsPresent(&iIntVal))
{
// Set int
SetKeyL(iIntVal);
}
else if (iOptions.IsPresent(&iStringVal))
{
// Set string
//TPtrC8 data((TUint8*)iStringVal->Ptr(), iStringVal->Size());
//SetKeyL(data);
SetKeyL(*iStringVal);
}
else if (!iArguments.IsPresent(1))
{
// Get all
if (iForce)
{
SudoL(KNullDesC);
}
else
{
RBuf8 valDes;
CleanupClosePushL(valDes);
valDes.CreateL(NCentralRepositoryConstants::KMaxBinaryLength);
RArray<TUint32> keys;
CleanupClosePushL(keys);
iRep->FindL(0, 0, keys);
for (TInt i = 0; i < keys.Count(); i++)
{
PrintKeyL(keys[i], valDes);
}
CleanupStack::PopAndDestroy(2, &valDes); // keys, valDes
}
}
else
{
// Get
RBuf8 valDes;
CleanupClosePushL(valDes);
valDes.CreateL(NCentralRepositoryConstants::KMaxBinaryLength * 3); // Because we also use this for hexifying
PrintKeyL(iKey, valDes);
CleanupStack::PopAndDestroy(&valDes);
}
}
template <class KEYTYPE>
void CCmdCenrep::SetKeyL(const KEYTYPE& aVal)
{
if (!iArguments.IsPresent(1))
{
LeaveIfErr(KErrArgument, _L("You must specify a key to set"));
}
if (iForce)
{
ForceSetKeyL(aVal);
}
else
{
TInt err = iRep->Set(iKey, aVal);
if (err == KErrArgument)
{
PrintError(err, _L("Key does not appear to be of the right type"));
}
User::LeaveIfError(err);
}
}
void CCmdCenrep::ForceSetKeyL(TInt aVal)
{
SudoL(_L("%d --set-int %d"), iKey, aVal);
}
void CCmdCenrep::ForceSetKeyL(const TDesC& aVal)
{
SudoL(_L("%d --set-string '%S'"), iKey, &aVal);
}
void CCmdCenrep::PrintKeyL(TUint aKey, RBuf8& valDes)
{
TInt valInt;
valDes.Zero();
enum TType { EUnknown, EInt, EDes };
TType type = EUnknown;
TInt reallen = 0;
TInt err = KErrNotFound;
if (iForce)
{
SudoL(_L("%d"), aKey);
}
else
{
// Guess the value type
// Int?
if (type == EUnknown)
{
err = iRep->Get(aKey, valInt);
if (err != KErrArgument)
{
type = EInt;
}
}
if (type == EUnknown)
{
// Des?
err = iRep->Get(aKey, valDes, reallen);
if (err != KErrArgument)
{
type = EDes;
}
}
}
switch(err)
{
case KErrNotFound:
PrintError(err, _L("Key not found"));
break;
case KErrArgument:
PrintError(err, _L("Unknown key type, not int, des8 or des16"));
break;
case KErrPermissionDenied:
PrintError(err, _L("Permission denied, retry with --force"));
break;
/* Won't happen because we now set our buffers to be the max size cenrep can handle
case KErrOverflow:
valDes16.ReallocL(reallen);
valDes8.ReallocL(reallen);
if (type == EDes8)
{
err = rep->Get(iKey, valDes8, reallen); // Better not fail this time!
}
else
{
err = rep->Get(iKey, valDes16, reallen); // Better not fail this time!
}
*/
case KErrNone:
// do nothing
break;
default:
PrintError(err, _L("Unrecognised error returned from CRepository"));
break;
}
if (err == KErrNone)
{
switch (type)
{
case EInt:
Printf(_L("Key 0x%08x TInt: %d (0x%x)\r\n"), aKey, valInt, valInt);
break;
/*case EDes8:
valDes16.Copy(valDes8);
Printf(_L("Key 0x%x TDesC8 length=%d: %S\r\n"), aKey, valDes16.Length(), &valDes16);
break;*/
case EDes:
{
TInt len = valDes.Length();
// Figure out if this string is likely to be 16bit ASCII, 8bit ASCII or just binary data
TBool wide = ETrue;
TBool ascii = ETrue;
if (len&1) wide = EFalse; // Odd number of bytes can't be 16-bit
for (TInt i = 0; i < len; i++)
{
TChar c(valDes[i]);
if ((i&1) && valDes[i] != 0) wide = EFalse;
if (!(c.IsPrint() && c < 127))
{
if (!(i&1)) wide = EFalse;
ascii = EFalse;
}
}
if (wide)
{
TPtr16 widePtr((TUint16*)valDes.Ptr(), len/2, valDes.MaxLength()/2);
Printf(_L("Key 0x%08x TDesC16 length=%d: %S\r\n"), aKey, widePtr.Length(), &widePtr);
}
else if (ascii)
{
Printf(_L8("Key 0x%08x TDesC8 length=%d: %S\r\n"), aKey, len, &valDes);
}
else
{
Printf(_L("Key 0x%08x TDesC8 hex dump:\r\n"), aKey);
LtkUtils::HexDumpToOutput(valDes, Stdout());
}
}
break;
default:
break;
}
}
}
void CCmdCenrep::ArgumentsL(RCommandArgumentList& aArguments)
{
aArguments.AppendUintL(iRepository, _L("repository_uid"));
aArguments.AppendUintL(iKey, _L("key"));
}
void CCmdCenrep::OptionsL(RCommandOptionList& aOptions)
{
aOptions.AppendIntL(iIntVal, _L("set-int"));
aOptions.AppendStringL(iStringVal, _L("set-string"));
aOptions.AppendBoolL(iForce, _L("force"));
aOptions.AppendBoolL(iDelete, _L("delete"));
aOptions.AppendBoolL(iReset, _L("reset"));
}
EXE_BOILER_PLATE(CCmdCenrep)
void CCmdCenrep::ListRepositoriesL()
{
RArray<TUint> uids;
CleanupClosePushL(uids);
AddFilesL(uids, _L("*.cre"), _L("Y:\\private\\10202be9\\persists\\"));
AddFilesL(uids, _L("*.cre"), _L("Y:\\private\\10202be9\\"));
AddFilesL(uids, _L("*.txt"), _L("Y:\\private\\10202be9\\"));
for (TInt i = 0; i < uids.Count(); i++)
{
Printf(_L("%08x\r\n"), uids[i]);
}
CleanupStack::PopAndDestroy(&uids);
}
void CCmdCenrep::AddFilesL(RArray<TUint>& aUids, const TDesC& aMatch, const TDesC& aDir)
{
TFindFile finder(FsL());
CDir* files = NULL;
TInt err = finder.FindWildByDir(aMatch, aDir, files);
while (err == KErrNone)
{
for (TInt i = 0; i < files->Count(); i++)
{
TUint uid;
TLex lex((*files)[i].iName);
err = lex.Val(uid, EHex);
if (!err)
{
err = aUids.InsertInOrder(uid);
if (err == KErrAlreadyExists) err = KErrNone;
}
}
delete files;
files = NULL;
err = finder.FindWild(files);
}
if (err && err != KErrNotFound) LeaveIfErr(err, _L("Couldn't read directory %S"), &aDir);
}
void CCmdCenrep::SudoL(TRefByValue<const TDesC> aFmt, ...)
{
VA_LIST args;
VA_START(args, aFmt);
// We use sudo to give ourselves the SID of the repository, in the hope that will confer us more rights to access the data.
// Some repos might be configured to deny access even from their own SID; there's nothing we can do in that case
TBuf<256> commandLine;
commandLine.AppendFormat(_L("--sid 0x%x cenrep.exe 0x%x "), iRepository, iRepository);
commandLine.AppendFormatList(aFmt, args);
VA_END(args);
RChildProcess sudo;
CleanupClosePushL(sudo);
TRAPL(sudo.CreateL(_L("sudo.exe"), commandLine, IoSession(), Stdin(), Stdout(), Stderr()), _L("Couldn't create sudo process"));
TRequestStatus logon;
sudo.Run(logon);
User::WaitForRequest(logon);
LeaveIfErr(logon.Int(), _L("Error running sudo %S"), &commandLine);
CleanupStack::PopAndDestroy(&sudo);
}