commands/localdrive/localdrive.cpp
changeset 0 7f656887cf89
child 26 5d370dafea69
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // localdrive.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <fshell/ioutils.h>
       
    14 #include <fshell/common.mmh>
       
    15 #include <d32locd.h>
       
    16 
       
    17 using namespace IoUtils;
       
    18 
       
    19 class CCmdLocalDrive : public CCommandBase
       
    20 	{
       
    21 public:
       
    22 	static CCommandBase* NewLC();
       
    23 	~CCmdLocalDrive();
       
    24 private:
       
    25 	CCmdLocalDrive();
       
    26 	TInt OpenL(TInt aDrive, TBool aLeaveOnConnectErr);
       
    27 private: // From CCommandBase.
       
    28 	virtual const TDesC& Name() const;
       
    29 	virtual void DoRunL();
       
    30 	virtual void ArgumentsL(RCommandArgumentList& aArguments);
       
    31 	virtual void OptionsL(RCommandOptionList& aOptions);
       
    32 private:
       
    33 	enum TCmd
       
    34 		{
       
    35 		EList,
       
    36 		ERead,
       
    37 		EWrite,
       
    38 		};
       
    39 	TInt iDriveNum;
       
    40 	TCmd iCmd;
       
    41 	TBool iSizesInBytes;
       
    42 	TFileName2 iFile;
       
    43 
       
    44 	RLocalDrive iDrive;
       
    45 	TLocalDriveCapsV2 iCaps;
       
    46 	};
       
    47 
       
    48 EXE_BOILER_PLATE(CCmdLocalDrive)
       
    49 
       
    50 CCommandBase* CCmdLocalDrive::NewLC()
       
    51 	{
       
    52 	CCmdLocalDrive* self = new(ELeave) CCmdLocalDrive();
       
    53 	CleanupStack::PushL(self);
       
    54 	self->BaseConstructL();
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 CCmdLocalDrive::~CCmdLocalDrive()
       
    59 	{
       
    60 	iDrive.Close();
       
    61 	}
       
    62 
       
    63 CCmdLocalDrive::CCmdLocalDrive()
       
    64 	{
       
    65 	}
       
    66 
       
    67 const TDesC& CCmdLocalDrive::Name() const
       
    68 	{
       
    69 	_LIT(KName, "localdrive");	
       
    70 	return KName;
       
    71 	}
       
    72 
       
    73 void CCmdLocalDrive::ArgumentsL(RCommandArgumentList& aArguments)
       
    74 	{
       
    75 	aArguments.AppendEnumL((TInt&)iCmd, _L("operation"));
       
    76 	aArguments.AppendIntL(iDriveNum, _L("drive"));
       
    77 	}
       
    78 
       
    79 void CCmdLocalDrive::OptionsL(RCommandOptionList& aOptions)
       
    80 	{
       
    81 	aOptions.AppendBoolL(iSizesInBytes, _L("bytes"));
       
    82 	aOptions.AppendFileNameL(iFile, _L("file"));
       
    83 	}
       
    84 
       
    85 // More GCC issues (see qresources3\src\utils.cpp). Happily the compiler is happier with SLitC and DESC than it is with TLitC and _LIT
       
    86 #include <fshell/descriptorutils.h>
       
    87 #define CASE_LIT(x) case x: { LtkUtils::SLitC KName = DESC(#x); return &KName; }
       
    88 
       
    89 const TDesC* MediaTypeDesc(TMediaType aType)
       
    90 	{
       
    91 	enum TEnumsNotIn91
       
    92 		{
       
    93 		EMediaRotatingMedia = EMediaNANDFlash + 1,
       
    94 		};
       
    95 	switch (aType)
       
    96 		{
       
    97 		CASE_LIT(EMediaNotPresent)
       
    98 		CASE_LIT(EMediaUnknown)
       
    99 		CASE_LIT(EMediaFloppy)
       
   100 		CASE_LIT(EMediaHardDisk)
       
   101 		CASE_LIT(EMediaCdRom)
       
   102 		CASE_LIT(EMediaRam)
       
   103 		CASE_LIT(EMediaFlash)
       
   104 		CASE_LIT(EMediaRom)
       
   105 		CASE_LIT(EMediaRemote)
       
   106 		CASE_LIT(EMediaNANDFlash)
       
   107 		CASE_LIT(EMediaRotatingMedia)
       
   108 		default:
       
   109 			{
       
   110 			_LIT(KUnknown, "?");
       
   111 			return &KUnknown;
       
   112 			}
       
   113 		}
       
   114 	}
       
   115 
       
   116 void CCmdLocalDrive::DoRunL()
       
   117 	{
       
   118 	if (iCmd == EList)
       
   119 		{
       
   120 		for (TInt i = 0; i < KMaxLocalDrives; i++)
       
   121 			{
       
   122 			if (iArguments.IsPresent(&iDriveNum) && i != iDriveNum) continue;
       
   123 			TInt err = OpenL(i, EFalse);
       
   124 			if (err == KErrNone)
       
   125 				{
       
   126 				CTextBuffer* buf = CTextBuffer::NewLC(256);
       
   127 				buf->AppendFormatL(_L("Found drive %d partitionType=0x%x mediatype=%S(%d) size="), i, iCaps.iPartitionType, MediaTypeDesc(iCaps.iType), iCaps.iType);
       
   128 				if (iSizesInBytes)
       
   129 					{
       
   130 					buf->AppendFormatL(_L("%Ld"), iCaps.iSize);
       
   131 					}
       
   132 				else
       
   133 					{
       
   134 					buf->AppendHumanReadableSizeL(iCaps.iSize, EUnaligned);
       
   135 					}
       
   136 				if (iCaps.iType == EMediaFlash)
       
   137 					{
       
   138 					// NOR flash
       
   139 					buf->AppendFormatL(_L(" eraseblocksize=%d"), iCaps.iEraseBlockSize);
       
   140 					}
       
   141 
       
   142 				buf->AppendL(_L("\r\n"));
       
   143 				buf->Write(Stdout());
       
   144 				CleanupStack::PopAndDestroy(buf);
       
   145 				}
       
   146 			iDrive.Close();
       
   147 			}
       
   148 		}
       
   149 	else if (iCmd == ERead)
       
   150 		{
       
   151 		if (!iArguments.IsPresent(&iDriveNum)) LeaveIfErr(KErrArgument, _L("Must supply <drive> argument for the read command"));
       
   152 		OpenL(iDriveNum, ETrue);
       
   153 		RFile file;
       
   154 		CleanupClosePushL(file);
       
   155 		const TInt KBufSize = 32*1024;
       
   156 		RBuf8 buf;
       
   157 		CleanupClosePushL(buf);
       
   158 		if (iFile.Length())
       
   159 			{
       
   160 			LeaveIfErr(file.Create(FsL(), iFile, EFileWrite), _L("Couldn't create file %S"), &iFile);
       
   161 			buf.CreateL(KBufSize);
       
   162 			}
       
   163 		else
       
   164 			{
       
   165 			LeaveIfErr(Stdout().SetMode(RIoReadWriteHandle::EBinary), _L("Unable to set stdout to binary mode"));
       
   166 			buf.CreateL(KBufSize*2);
       
   167 			}
       
   168 
       
   169 		TInt64 bytesRead = 0;
       
   170 		while (bytesRead < iCaps.iSize)
       
   171 			{
       
   172 			buf.Zero();
       
   173 			LeaveIfErr(iDrive.Read(bytesRead, KBufSize, buf), _L("Failed to read %Ld+%d bytes from partition"), bytesRead, KBufSize);
       
   174 			bytesRead += buf.Length();
       
   175 			if (file.SubSessionHandle())
       
   176 				{
       
   177 				LeaveIfErr(file.Write(buf), _L("Couldn't write %d bytes to file"), buf.Length());
       
   178 				}
       
   179 			else
       
   180 				{
       
   181 				Stdout().Write(buf.Expand());
       
   182 				}
       
   183 			}
       
   184 		CleanupStack::PopAndDestroy(2, &file); // buf, file
       
   185 		}
       
   186 	else if (iCmd == EWrite)
       
   187 		{
       
   188 		if (!iArguments.IsPresent(&iDriveNum)) LeaveIfErr(KErrArgument, _L("Must supply <drive> argument for the write command"));
       
   189 		if (!iOptions.IsPresent(&iFile)) LeaveIfErr(KErrArgument, _L("Must supply file name argument for the write command, using --file"));
       
   190 
       
   191 		OpenL(iDriveNum, ETrue);
       
   192 		RFile file;
       
   193 		CleanupClosePushL(file);
       
   194 		const TInt KBufSize = 32*1024;
       
   195 		RBuf8 buf;
       
   196 		CleanupClosePushL(buf);
       
   197 		LeaveIfErr(file.Open(FsL(), iFile, EFileRead), _L("Couldn't open file %S"), &iFile);
       
   198 		TInt fileSize;
       
   199 		LeaveIfErr(file.Size(fileSize), _L("Couldn't read file size"));
       
   200 		if (fileSize != iCaps.iSize) LeaveIfErr(KErrNotReady, _L("File size (%d) does not match partition size (%d)"), fileSize, (TInt)iCaps.iSize);
       
   201 
       
   202 		buf.CreateL(KBufSize);
       
   203 
       
   204 		TInt64 bytesRead = 0;
       
   205 		while (bytesRead < fileSize)
       
   206 			{
       
   207 			buf.Zero();
       
   208 			LeaveIfErr(file.Read(buf), _L("Failed to read file"));
       
   209 			LeaveIfErr(iDrive.Write(bytesRead, buf), _L("Couldn't write %d bytes to flash at partition offset %Ld"), buf.Length(), bytesRead);
       
   210 			bytesRead += buf.Length();
       
   211 			}
       
   212 		CleanupStack::PopAndDestroy(2, &file); // buf, file
       
   213 		}
       
   214 	else
       
   215 		{
       
   216 		LeaveIfErr(KErrArgument, _L("Unrecognised operation %d"), iCmd);
       
   217 		}
       
   218 	}
       
   219 
       
   220 TInt CCmdLocalDrive::OpenL(TInt aDrive, TBool aLeaveOnConnectErr)
       
   221 	{
       
   222 	if (aDrive >= KMaxLocalDrives) LeaveIfErr(KErrArgument, _L("drive number %d is outside of KMaxLocalDrives (%d)"), aDrive, KMaxLocalDrives);
       
   223 
       
   224 	TBool changed; // What is this for?
       
   225 	TInt err = iDrive.Connect(aDrive, changed);
       
   226 	if (err == KErrNone)
       
   227 		{
       
   228 		TPckg<TLocalDriveCapsV2> capsBuf(iCaps);
       
   229 		LeaveIfErr(iDrive.Caps(capsBuf), _L("Opened drive %d but couldn't read caps"), aDrive);
       
   230 		}
       
   231 	else if (aLeaveOnConnectErr)
       
   232 		{
       
   233 		LeaveIfErr(err, _L("Couldn't open drive %d"), aDrive);
       
   234 		}
       
   235 	return err;
       
   236 	}