diff -r 000000000000 -r 7f656887cf89 commands/localdrive/localdrive.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/localdrive/localdrive.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,236 @@ +// 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 +#include +#include + +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 +#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 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 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 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; + }