Tidied iocli exports, build macro tweaks.
Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll.
fixed builds on platforms that don't support btrace or any form of tracing.
// localdrive.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/ioutils.h>
#include <fshell/common.mmh>
#include <d32locd.h>
using namespace IoUtils;
class CCmdLocalDrive : public CCommandBase
{
public:
static CCommandBase* NewLC();
~CCmdLocalDrive();
private:
CCmdLocalDrive();
TInt OpenL(TInt aDrive, TBool aLeaveOnConnectErr);
private: // From CCommandBase.
virtual const TDesC& Name() const;
virtual void DoRunL();
virtual void ArgumentsL(RCommandArgumentList& aArguments);
virtual void OptionsL(RCommandOptionList& aOptions);
private:
enum TCmd
{
EList,
ERead,
EWrite,
};
TInt iDriveNum;
TCmd iCmd;
TBool iSizesInBytes;
TFileName2 iFile;
RLocalDrive iDrive;
TLocalDriveCapsV2 iCaps;
};
EXE_BOILER_PLATE(CCmdLocalDrive)
CCommandBase* CCmdLocalDrive::NewLC()
{
CCmdLocalDrive* self = new(ELeave) CCmdLocalDrive();
CleanupStack::PushL(self);
self->BaseConstructL();
return self;
}
CCmdLocalDrive::~CCmdLocalDrive()
{
iDrive.Close();
}
CCmdLocalDrive::CCmdLocalDrive()
{
}
const TDesC& CCmdLocalDrive::Name() const
{
_LIT(KName, "localdrive");
return KName;
}
void CCmdLocalDrive::ArgumentsL(RCommandArgumentList& aArguments)
{
aArguments.AppendEnumL((TInt&)iCmd, _L("operation"));
aArguments.AppendIntL(iDriveNum, _L("drive"));
}
void CCmdLocalDrive::OptionsL(RCommandOptionList& aOptions)
{
aOptions.AppendBoolL(iSizesInBytes, _L("bytes"));
aOptions.AppendFileNameL(iFile, _L("file"));
}
// More GCC issues (see qresources3\src\utils.cpp). Happily the compiler is happier with SLitC and DESC than it is with TLitC and _LIT
#include <fshell/descriptorutils.h>
#define CASE_LIT(x) case x: { LtkUtils::SLitC KName = DESC(#x); return &KName; }
const TDesC* MediaTypeDesc(TMediaType aType)
{
enum TEnumsNotIn91
{
EMediaRotatingMedia = EMediaNANDFlash + 1,
};
switch (aType)
{
CASE_LIT(EMediaNotPresent)
CASE_LIT(EMediaUnknown)
CASE_LIT(EMediaFloppy)
CASE_LIT(EMediaHardDisk)
CASE_LIT(EMediaCdRom)
CASE_LIT(EMediaRam)
CASE_LIT(EMediaFlash)
CASE_LIT(EMediaRom)
CASE_LIT(EMediaRemote)
CASE_LIT(EMediaNANDFlash)
CASE_LIT(EMediaRotatingMedia)
default:
{
_LIT(KUnknown, "?");
return &KUnknown;
}
}
}
void CCmdLocalDrive::DoRunL()
{
if (iCmd == EList)
{
for (TInt i = 0; i < KMaxLocalDrives; i++)
{
if (iArguments.IsPresent(&iDriveNum) && i != iDriveNum) continue;
TInt err = OpenL(i, EFalse);
if (err == KErrNone)
{
CTextBuffer* buf = CTextBuffer::NewLC(256);
buf->AppendFormatL(_L("Found drive %d partitionType=0x%x mediatype=%S(%d) size="), i, iCaps.iPartitionType, MediaTypeDesc(iCaps.iType), iCaps.iType);
if (iSizesInBytes)
{
buf->AppendFormatL(_L("%Ld"), iCaps.iSize);
}
else
{
buf->AppendHumanReadableSizeL(iCaps.iSize, EUnaligned);
}
if (iCaps.iType == EMediaFlash)
{
// NOR flash
buf->AppendFormatL(_L(" eraseblocksize=%d"), iCaps.iEraseBlockSize);
}
buf->AppendL(_L("\r\n"));
buf->Write(Stdout());
CleanupStack::PopAndDestroy(buf);
}
iDrive.Close();
}
}
else if (iCmd == ERead)
{
if (!iArguments.IsPresent(&iDriveNum)) LeaveIfErr(KErrArgument, _L("Must supply <drive> argument for the read command"));
OpenL(iDriveNum, ETrue);
RFile file;
CleanupClosePushL(file);
const TInt KBufSize = 32*1024;
RBuf8 buf;
CleanupClosePushL(buf);
if (iFile.Length())
{
LeaveIfErr(file.Create(FsL(), iFile, EFileWrite), _L("Couldn't create file %S"), &iFile);
buf.CreateL(KBufSize);
}
else
{
LeaveIfErr(Stdout().SetMode(RIoReadWriteHandle::EBinary), _L("Unable to set stdout to binary mode"));
buf.CreateL(KBufSize*2);
}
TInt64 bytesRead = 0;
while (bytesRead < iCaps.iSize)
{
buf.Zero();
LeaveIfErr(iDrive.Read(bytesRead, KBufSize, buf), _L("Failed to read %Ld+%d bytes from partition"), bytesRead, KBufSize);
bytesRead += buf.Length();
if (file.SubSessionHandle())
{
LeaveIfErr(file.Write(buf), _L("Couldn't write %d bytes to file"), buf.Length());
}
else
{
Stdout().Write(buf.Expand());
}
}
CleanupStack::PopAndDestroy(2, &file); // buf, file
}
else if (iCmd == EWrite)
{
if (!iArguments.IsPresent(&iDriveNum)) LeaveIfErr(KErrArgument, _L("Must supply <drive> argument for the write command"));
if (!iOptions.IsPresent(&iFile)) LeaveIfErr(KErrArgument, _L("Must supply file name argument for the write command, using --file"));
OpenL(iDriveNum, ETrue);
RFile file;
CleanupClosePushL(file);
const TInt KBufSize = 32*1024;
RBuf8 buf;
CleanupClosePushL(buf);
LeaveIfErr(file.Open(FsL(), iFile, EFileRead), _L("Couldn't open file %S"), &iFile);
TInt fileSize;
LeaveIfErr(file.Size(fileSize), _L("Couldn't read file size"));
if (fileSize != iCaps.iSize) LeaveIfErr(KErrNotReady, _L("File size (%d) does not match partition size (%d)"), fileSize, (TInt)iCaps.iSize);
buf.CreateL(KBufSize);
TInt64 bytesRead = 0;
while (bytesRead < fileSize)
{
buf.Zero();
LeaveIfErr(file.Read(buf), _L("Failed to read file"));
LeaveIfErr(iDrive.Write(bytesRead, buf), _L("Couldn't write %d bytes to flash at partition offset %Ld"), buf.Length(), bytesRead);
bytesRead += buf.Length();
}
CleanupStack::PopAndDestroy(2, &file); // buf, file
}
else
{
LeaveIfErr(KErrArgument, _L("Unrecognised operation %d"), iCmd);
}
}
TInt CCmdLocalDrive::OpenL(TInt aDrive, TBool aLeaveOnConnectErr)
{
if (aDrive >= KMaxLocalDrives) LeaveIfErr(KErrArgument, _L("drive number %d is outside of KMaxLocalDrives (%d)"), aDrive, KMaxLocalDrives);
TBool changed; // What is this for?
TInt err = iDrive.Connect(aDrive, changed);
if (err == KErrNone)
{
TPckg<TLocalDriveCapsV2> capsBuf(iCaps);
LeaveIfErr(iDrive.Caps(capsBuf), _L("Opened drive %d but couldn't read caps"), aDrive);
}
else if (aLeaveOnConnectErr)
{
LeaveIfErr(err, _L("Couldn't open drive %d"), aDrive);
}
return err;
}