dbgsrv/coredumpserver/plugins/writers/file/src/filewriter.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgsrv/coredumpserver/plugins/writers/file/src/filewriter.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,480 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// @file filewriter.cpp
+// Implementation of the file writer plugin.
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+#include <e32debug.h>
+#include <optionconfig.h>
+#include <bautils.h>
+#include "filewriter.h"
+
+/**
+1st stage construction
+@return pointer to the newly created object, user takes ownership of the object.
+*/
+CFileWriter* CFileWriter::NewL()
+    {
+	//LOG_MSG("->CFileWriter::NewL()\n");
+	CFileWriter* self = CFileWriter::NewLC();
+	CleanupStack::Pop();
+	return self;
+    }
+
+/**
+1st stage construction
+@return pointer to the newly created object, user takes ownership of the object.
+*/
+CFileWriter* CFileWriter::NewLC()
+    {
+	//LOG_MSG("->CFileWriter::NewLC()\n");
+	CFileWriter* self = new(ELeave) CFileWriter();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+    }
+
+/**
+ctor defaults plugin description descriptor to zero
+*/
+CFileWriter::CFileWriter() :
+	iDescription(0)
+{ }
+
+/**
+2nd stage construction.
+Connects to the file server, reserves config parameter list,
+creates config parameter objects and sets them to default values.
+*/
+void CFileWriter::ConstructL()
+    {
+	//LOG_MSG("->CFileWriter::ConstructL()\n");
+    TInt err;
+
+	_LIT(KPluginDescription, "Symbian Elf Core Dump Writer");
+	iDescription = KPluginDescription().AllocL();
+    iFs.Connect();
+    iFs.ShareAuto(); //share the session with the crash processing thread
+
+	iConfigList.ReserveL( (TInt)EDataSaveLastParam );
+
+	COptionConfig *config;
+
+	_LIT( KFilePathPrompt, "Please supply Full Core Dump Filepath (eg \"C:\\coredump.core\")" );
+	config = COptionConfig::NewL(  (TInt)ECoreFilePath,
+									KFileWriterUid,								// UID, unused
+									COptionConfig::EWriterPlugin,
+									COptionConfig::ETFileName,
+									KFilePathPrompt,
+                                    1,
+									KNullDesC,
+									0,
+									KNullDesC );
+
+	err = iConfigList.Append( config );
+    if(err != KErrNone)
+        {
+	    LOG_MSG2("CFileWriter::ConstructL - unable to append the param! err:%d\n", err);
+        delete config;
+        User::Leave(err);
+        }
+    }
+
+/**
+dtor frees config parameter list, plugin description descriptor and closes file server session.
+*/
+CFileWriter::~CFileWriter()
+    {
+    iConfigList.ResetAndDestroy();
+	delete iDescription;
+	iFs.Close();
+    }
+
+/**
+Returns a description of the plugin.
+@param aPluginDescription Output parameter that contains the plugin description.
+*/
+void CFileWriter::GetDescription( TDes & aPluginDescription )
+    {
+	aPluginDescription = *iDescription;
+    }
+
+/**
+Called by CDS to ask for the configuration parameters that the writer implements.
+@return actual number of implemented config parameters
+*/
+TInt CFileWriter::GetNumberConfigParametersL()
+	{
+	//LOG_MSG2("CFileWriter::GetNumberConfigParametersL()\n", iConfigList.Count() );
+	return iConfigList.Count();
+	}
+
+/**
+Called by CDS to ask for configuration parameter.
+@param aIndex indicates which parameter to return
+@return pointer to COptionConfig object representing the requested config parameter. Caller doesn't take ownership of the object!
+@leave KErrBadHandle if index is out of bounds
+@see COptionConfig
+*/
+COptionConfig * CFileWriter::GetConfigParameterL( const TInt aIndex )
+	{
+	// return the config identified by aIndex
+	if( ( aIndex < 0 ) || ( aIndex >= iConfigList.Count() ) )
+		{
+		User::Leave( KErrBadHandle );
+		}
+
+    return iConfigList[aIndex];
+	}
+
+/**
+Change a configuration parameter.
+@param aIndex Index of parameter to change
+@param aValue Unused
+@param aDescValue Path and filename to use
+@leave KErrBadHandle if index is out of bounds, KErrBadName if file name parameter is not a valid file name or one of the other system wide error codes
+*/
+void CFileWriter::SetConfigParameterL( const TInt aIndex, const TInt32 & aValue, const TDesC & aDescValue )
+    {
+	// Make the changes to our internal structures, and reflect such changes in our behaviour
+	if( ( aIndex < 0 ) || ( aIndex > iConfigList.Count() ) )
+		{
+		LOG_MSG2("CFileWriter::SetConfigParameterL - bad param request %d", aIndex );
+		User::Leave( KErrBadHandle );
+		}
+
+	COptionConfig & config = *(iConfigList[aIndex]);
+	if( aIndex == (TInt)ECoreFilePath )
+		{
+		if( iFs.IsValidName( aDescValue ) || aDescValue == KNullDesC )
+			{
+			config.ValueL( aDescValue );
+			}
+		else
+			{
+			_LIT( KInvalidFileErrorMsg ,"File Writer Error : Filepath Not Valid");
+			User::InfoPrint( KInvalidFileErrorMsg );
+			LOG_MSG(" CFileWriter::SetConfigParameterL() : ERROR  from RFs.IsValidName( )" );
+			User::Leave( KErrBadName );
+			}
+		}
+	else
+		{
+		LOG_MSG2("CFileWriter::SetConfigParameterL - invalid aIndex:%d\n", aIndex );
+		User::Leave( KErrBadHandle );
+		}
+
+	//If the descriptor is not null ensure it is a valid path
+	if(aDescValue != KNullDesC)
+		{
+		TParse parseName;
+		TInt err = parseName.Set( aDescValue, NULL, NULL );
+		if( KErrNone != err )
+			{
+			_LIT( KParseFileErrorMsg ,"File Writer Error : Could not Parse Filepath");
+			User::InfoPrint( KParseFileErrorMsg );
+			LOG_MSG(" CFileWriter::SetConfigParameterL() : ERROR  from TParse.Set( )" );
+			User::Leave( err );
+			}
+
+		TPtrC drvpath = parseName.DriveAndPath();
+		RDir rDir;
+		TInt dirErr = rDir.Open( iFs, drvpath, EFileWrite );
+		rDir.Close();
+		if( KErrNone != dirErr )
+			{
+			_LIT( KInvalidDirErrorMsg ,"File Writer Error : Directory Does Not Exist");
+			User::InfoPrint( KInvalidDirErrorMsg );
+			LOG_MSG2(" CFileWriter::SetConfigParameterL() : ERROR  from RDir.Open() returned %d", dirErr );
+			User::Leave( KErrBadName );
+			}
+		}
+
+	//This is initially the filename we intend to, and will try to use
+	iFileName = aDescValue;
+    }
+
+/**
+Called by formatter to start the creation of a dump file.
+Can be called several times to create several files.
+Note that if the file specified either in the parameter here
+or the configuration already exists, the file writer will not 
+overwrite it, and instead just append a number in brackets to 
+the stem of the filename. e.g. e:\file(1).elf if e:\file.elf
+already exists. To determine the actual name used, call GetMediaName
+
+@see GetMediaName()
+@param aFileName Formatters can supply a file name to use
+@return one of the system error codes
+@leave err one of the system wide error codes
+*/
+void CFileWriter::OpenL( const TDesC& aFileName )
+    {
+    User::LeaveIfError(Open(aFileName));
+    }
+
+/**
+Called by formatter to start the creation of a dump file.
+Can be called several times to create several files.
+Note that if the file specified either in the parameter here
+or the configuration already exists, the file writer will not 
+overwrite it, and instead just append a number in brackets to 
+the stem of the filename. e.g. e:\file(1).elf if e:\file.elf
+already exists. To determine the actual name used, call GetMediaName
+
+@see GetMediaName()
+@param aFileName Formatters can supply a file name to use
+@return one of the system error codes
+*/
+TInt CFileWriter::Open( const TDesC& aFileName )
+	{
+    if(aFileName.Length() > 0)
+        {
+		iFileName = aFileName;
+        }
+    else
+        {
+		COptionConfig & config = *(iConfigList[ (TInt)ECoreFilePath ]);
+		iFileName = config.ValueAsDesc();
+	    }
+
+	LOG_MSG2("->CFileWriter::Open([%S])\n", &TPtr8((TUint8*)iFileName.Ptr(), 2*iFileName.Length(),	2*iFileName.Length() ));
+
+	//If the file exists already, we want to preserve it, and append a (%d) to the name of the new file
+	const TUint startAppend = 1;
+	TUint currentAppend = startAppend;
+	TBuf<KMaxFileName> formatString;
+
+	_LIT(KFormatString, "(%d)");
+	_LIT(KFileBackSlash, "\\");
+
+	for(;;)
+		{
+		//If file doesn't exist, we can use this name
+		if(!BaflUtils::FileExists(iFs, iFileName))
+			break;
+
+		//otherwise, we sort out the filename
+		if(currentAppend == startAppend)
+			{
+			//first time so it needs the (%d) at the end of the name
+			TParse p;
+			p.Set(iFileName, NULL, NULL);
+
+			formatString.Append(p.Drive());
+			formatString.Append(KFileBackSlash);
+			formatString.Append(p.Name());
+			formatString.Append(KFormatString);
+			formatString.Append(p.Ext());
+			}
+
+		iFileName.Format(formatString, currentAppend);
+		++currentAppend;
+		}
+
+	return iFile.Create(iFs, iFileName, EFileWrite);
+    }
+
+/**
+This returns a reference to a descriptor containing the name
+of the file that the filewriter intends to use at any point 
+in time. Note that the filewriter will not determine what file
+to use until the last moment and so this is not gauranteed to 
+be the actual filename used until one of the Open() methods are
+called
+
+@see Open(const TDesC& aFileName)
+@see OpenL(const TDesC& aFileName)
+@return TDesC& reference to filename
+*/
+const TDesC& CFileWriter::GetMediaName()
+	{
+	return iFileName;	
+	}
+
+/**
+Called by formatter at the end of the creation of a dump.
+Open() and Close() must be paired calls
+@pre Must have called Open() or OpenL()
+@leave err one of the system wide error codes
+*/
+void CFileWriter::CloseL()
+    {
+	User::LeaveIfError(Close());
+    }
+
+/**
+Called by formatter at the end of the creation of a dump.
+Open() and Close() must be paired calls
+@return one of the system wide error codes
+*/
+TInt CFileWriter::Close()
+    {
+    TInt err = iFile.Flush();
+    //LOG_MSG2("->CFileWriter::Close() : returns:%d\n", err);
+    iFile.Close();
+	return err;
+    }
+
+/**
+Save binary aData
+
+@param aData Binary data to save
+@leave err one of the system wide error codes
+*/
+void CFileWriter::WriteL( const TDesC8& aData )
+    {
+    User::LeaveIfError(Write(aData));
+    }
+
+/**
+Save binary aData
+
+@param aData Binary data to save
+@return one of the system wide error codes
+*/
+TInt CFileWriter::Write( const TDesC8& aData )
+    {
+    TInt err = iFile.Write(aData);
+    if( KErrNone != err )
+		{
+		LOG_MSG2("CFileWriter::Write() : iFile.Write(aData) returned :%d\n", err);
+		}
+    return err;
+    }
+
+/**
+Save aSize bytes of binary data.
+
+@param aData Binary data to save
+@param aSize Number of bytes to save
+@leave err one of the system wide error codes
+*/
+void CFileWriter::WriteL( TAny* aData, TUint aSize )
+    {
+    User::LeaveIfError(Write(aData, aSize));
+    }
+
+/**
+Save aSize bytes of binary data
+
+@param aData Binary data to save
+@param aSize Number of bytes to save
+@return one of the system wide error codes
+*/
+TInt CFileWriter::Write( TAny* aData, TUint aSize )
+    {
+    //LOG_MSG2("->CFileWriter::Writer(size=%d)\n", aSize);
+    if(aData == NULL)
+		{
+		LOG_MSG2("CFileWriter::Writer(size=%d), aData == NULL\n", aSize);
+        return KErrBadHandle;
+		}
+
+    TPtrC8 data(static_cast<TUint8*>(aData), aSize);
+    return( Write(data) );
+    }
+
+/**
+Save all of aData to file. Leaves if error.
+
+@param aPos Input : Position to write to, in bytes.
+@param aData Input : Data to write to file
+@leave err one of the system wide error codes
+@see RFile
+*/
+void CFileWriter::WriteL( TInt aPos, const TDesC8& aData )
+    {
+    User::LeaveIfError(Write(aPos, aData));
+    }
+
+/**
+Save all of aData to file.
+Note that if a position beyond the end of the file is specified,
+then the write operation begins at the end of the file.
+Thus aPos must be within the file written so far. For example
+writing at position 10 when that position has no data yet will
+result in the data being written at the end of the current file.
+This is a limitation of RFile.
+
+@param aPos Input : Position to write to, in bytes.
+@param aData Input : Data to write to file
+@return Returns error from RFile::Write()
+@see RFile
+*/
+TInt CFileWriter::Write( TInt aPos, const TDesC8& aData )
+    {
+//	LOG_MSG2("  iFile.Write(aPos=%d, aData)\n", aPos );
+    TInt err = iFile.Write(aPos, aData);
+    if( KErrNone != err )
+		{
+ 		LOG_MSG3("CFileWriter::Write() : iFile.Write(aPos=%d, aData) returned :%d\n", aPos, err );
+		}
+
+    return err;
+    }
+
+/**
+Save aSize bytes of aData at file position aPos.
+Note that if a position beyond the end of the file is specified,
+then the write operation begins at the end of the file.
+Thus aPos must be within the file written so far. For example
+writing at position 10 when that position has no data yet will
+result in the data being written at the end of the current file.
+This is a limitation of RFile.
+
+@param aPos Input : Position to write to, in bytes.
+@param aData Input : Data to write to file
+@param aSize Input : Number of bytes to write
+@leave err one of the system wide error codes
+@see RFile
+*/
+void CFileWriter::WriteL( TInt aPos, TAny* aData, TUint aSize )
+    {
+    User::LeaveIfError(Write(aPos, aData, aSize));
+    }
+
+/**
+Save aSize bytes of aData at file position aPos.
+Note that if a position beyond the end of the file is specified,
+then the write operation begins at the end of the file.
+Thus aPos must be within the file written so far. For example
+writing at position 10 when that position has no data yet will
+result in the data being written at the end of the current file.
+This is a limitation of RFile.
+
+@param aPos Input : Position to write to, in bytes.
+@param aData Input : Data to write to file
+@param aSize Input : Number of bytes to write
+@return one of the system wide error codes
+@see RFile
+*/
+TInt CFileWriter::Write( TInt aPos, TAny* aData, TUint aSize )
+    {
+    if(aData == NULL)
+        {
+		LOG_MSG3("CFileWriter::Writer(pos=%d, size=%d), aData == NULL\n", aPos, aSize);
+        return KErrNoMemory;
+        }
+
+    TPtrC8 data(static_cast<TUint8*>(aData), aSize);
+    return( Write(aPos, data) );
+    }