--- /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 <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;
+ }