diff -r 000000000000 -r 7f656887cf89 core/builtins/ymodem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/builtins/ymodem.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,283 @@ +// ymodem.cpp +// +// Copyright (c) 2008 - 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 "ymodem.h" + +using namespace IoUtils; + +CCommandBase* CCmdYmodem::NewLC() + { + CCmdYmodem* self = new(ELeave) CCmdYmodem(); + CleanupStack::PushL(self); + self->BaseConstructL(); + self->ConstructL(); + return self; + } + +CCmdYmodem::~CCmdYmodem() + { + iFileNames.Close(); + } + +CCmdYmodem::CCmdYmodem() + { + } + +const TDesC& CCmdYmodem::Name() const + { + _LIT(KName, "ymodem"); + return KName; + } + +class TFailedFile + { +public: + TFailedFile(); +public: + TInt iError; + TFileName2 iFileName; + }; + +TFailedFile::TFailedFile() + : iError(KErrNone) + { + } + +void CCmdYmodem::DoRunL() + { + PrepareConsoleToTransferL(); + + if (iMode == EReceive) + { + TPtrC receiveDir; + if (iFileNames.Count() > 1) + { + PrintError(KErrArgument, _L("Too many arguments - only the receive directory may be specified in receive mode.")); + User::Leave(KErrArgument); + } + else if (iFileNames.Count() == 1) + { + TFileName2 fileName(iFileNames[0]); + receiveDir.Set(iFileNames[0]); + + if ((fileName.Exists(FsL()) && !fileName.IsDirL(FsL())) || (!fileName.Exists(FsL()) && !iOverwrite)) + { + LeaveIfErr(KErrArgument, _L("\"%S\" is not a directory"), &fileName); + } + } + else + { + receiveDir.Set(Env().Pwd()); + } + + Progress(_L("YMODEM receive to \"%S\"\r\n"), &receiveDir); + RArray receivedFiles; + CleanupClosePushL(receivedFiles); + TFailedFile failedFile; + TBool finished(EFalse); + while (!finished) + { + TSyncResult syncResult = SendSyncL(); + if (syncResult == EEot) + { + finished = ETrue; + } + else + { + iPacketNumber = 0; + TBool isFinalBlock(EFalse); + TPtrC block(ReceiveBlockL(ETrue, isFinalBlock)); + TPtrC fileName(block.Ptr()); // filename is the first null terminated string in the block. + if (fileName.Length() > 0) + { + TFileName2 fileName2(fileName); + fileName2.MakeAbsoluteL(receiveDir); + TLex lex(block.Mid(fileName.Length() + 1)); + TInt size; + User::LeaveIfError(lex.Val(size)); + TInt err = KErrNone; + if (!iOverwrite && fileName2.Exists(FsL())) + { + err = KErrAlreadyExists; + } + RFile file; + if (err == KErrNone) + { + if (size == 0) + { + if (iOverwrite) + { + err = file.Replace(FsL(), fileName2, EFileWrite); + } + else + { + err = file.Create(FsL(), fileName2, EFileWrite); + } + } + else + { + Progress(_L("Starting receive of \"%S\" (%d bytes)\r\n"), &fileName, size); + SendSyncL(); + TRAP(err, ReceiveToFileL(fileName2)); + if (err == KErrNone) + { + err = file.Open(FsL(), fileName2, EFileWrite); + if (err == KErrNone) + { + err = file.SetSize(size); + } + } + else + { + Fs().Delete(fileName2); + } + } + } + else + { + TRAP_IGNORE(ReceiveToNullL()); + } + file.Close(); + if (err) + { + failedFile.iError = err; + failedFile.iFileName = fileName2; + finished = ETrue; + } + else + { + receivedFiles.Append(fileName2); // Ignore error. + } + } + else + { + finished = ETrue; + } + } + } + + CleanupClonsoleAfterTransferL(); + + const TInt numFilesReceived = receivedFiles.Count(); + if (numFilesReceived == 0) + { + if (failedFile.iError == KErrNone) + { + Printf(_L("No files to receive.\r\n")); + } + } + else if (numFilesReceived == 1) + { + const TFileName2& fileName = receivedFiles[0]; + Printf(_L("Successfully received \"%S\".\r\n"), &fileName); + } + else + { + Printf(_L("Successfully received:\r\n")); + for (TInt i = 0; i < numFilesReceived; ++i) + { + const TFileName2& fileName = receivedFiles[i]; + Printf(_L("\t\"%S\"\r\n"), &fileName); + } + } + + if (failedFile.iError) + { + PrintError(failedFile.iError, _L("Failed to receive \"%S\""), &failedFile.iFileName); + } + CleanupStack::PopAndDestroy(&receivedFiles); + } + else if (iMode == ESend) + { + const TInt numFiles = iFileNames.Count(); + if (numFiles == 0) + { + PrintError(KErrArgument, _L("No files to send specified")); + User::Leave(KErrArgument); + } + for (TInt i = 0; i < numFiles; ++i) + { + const TFileName2& fileName = iFileNames[i]; + if (fileName.Exists(FsL())) + { + if (fileName.IsDirL(FsL())) + { + LeaveIfErr(KErrArgument, _L("\"%S\" is not a file"), &fileName); + } + } + else + { + LeaveIfErr(KErrArgument, _L("\"%S\" does not exist"), &fileName); + } + } + WaitForSyncL(); + HBufC* buf = HBufC::NewLC(iBlockSize); + TPtr bufPtr(buf->Des()); + for (TInt i = 0; i < numFiles; ++i) + { + const TFileName2& fileName = iFileNames[i]; + LeaveIfFileNotFound(fileName); + TEntry entry; + User::LeaveIfError(FsL().Entry(fileName, entry)); + bufPtr.SetLength(bufPtr.MaxLength()); + bufPtr.FillZ(); + bufPtr.Copy(fileName.NameAndExt()); + bufPtr.SetLength(buf->Length() + 1); // To leave a terminating null after the file name. + bufPtr.AppendNum(entry.iSize); + if (bufPtr.Length() < iBlockSize) + { + // There's not enough data to fill this block, so pad with NULL. + bufPtr.AppendFill(0, iBlockSize - bufPtr.Length()); + } + iPacketNumber = 0; + SendBlockL(*buf); + WaitForSyncL(); + SendFileL(fileName); + } + iPacketNumber = 0; + bufPtr.SetLength(bufPtr.MaxLength()); + bufPtr.FillZ(); + SendBlockL(*buf); + CleanupStack::PopAndDestroy(buf); + CleanupClonsoleAfterTransferL(); + + if (numFiles == 1) + { + Printf(_L("Successfully sent \"%S\".\r\n"), &iFileNames[0]); + } + else + { + Printf(_L("Successfully sent:\r\n")); + for (TInt i = 0; i < numFiles; ++i) + { + const TFileName2& fileName = iFileNames[i]; + Printf(_L("\t\"%S\"\r\n"), &fileName); + } + } + } + User::LeaveIfError(Stdin().CancelCaptureAllKeys()); + } + +void CCmdYmodem::ArgumentsL(RCommandArgumentList& aArguments) + { + _LIT(KArg1, "mode"); + aArguments.AppendEnumL((TInt&)iMode, KArg1); + _LIT(KArg2, "file_name"); + aArguments.AppendFileNameL(iFileNames, KArg2); + } + +void CCmdYmodem::OptionsL(RCommandOptionList& aOptions) + { + CCmdXmodem::OptionsL(aOptions); + } +