dbgsrv/coredumpserver/plugins/writers/file/src/filewriter.cpp
changeset 0 c6b0df440bee
equal deleted inserted replaced
-1:000000000000 0:c6b0df440bee
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // @file filewriter.cpp
       
    15 // Implementation of the file writer plugin.
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalTechnology
       
    21  @released
       
    22 */
       
    23 
       
    24 #include <e32base.h>
       
    25 #include <e32debug.h>
       
    26 #include <optionconfig.h>
       
    27 #include <bautils.h>
       
    28 #include "filewriter.h"
       
    29 
       
    30 /**
       
    31 1st stage construction
       
    32 @return pointer to the newly created object, user takes ownership of the object.
       
    33 */
       
    34 CFileWriter* CFileWriter::NewL()
       
    35     {
       
    36 	//LOG_MSG("->CFileWriter::NewL()\n");
       
    37 	CFileWriter* self = CFileWriter::NewLC();
       
    38 	CleanupStack::Pop();
       
    39 	return self;
       
    40     }
       
    41 
       
    42 /**
       
    43 1st stage construction
       
    44 @return pointer to the newly created object, user takes ownership of the object.
       
    45 */
       
    46 CFileWriter* CFileWriter::NewLC()
       
    47     {
       
    48 	//LOG_MSG("->CFileWriter::NewLC()\n");
       
    49 	CFileWriter* self = new(ELeave) CFileWriter();
       
    50 	CleanupStack::PushL(self);
       
    51 	self->ConstructL();
       
    52 	return self;
       
    53     }
       
    54 
       
    55 /**
       
    56 ctor defaults plugin description descriptor to zero
       
    57 */
       
    58 CFileWriter::CFileWriter() :
       
    59 	iDescription(0)
       
    60 { }
       
    61 
       
    62 /**
       
    63 2nd stage construction.
       
    64 Connects to the file server, reserves config parameter list,
       
    65 creates config parameter objects and sets them to default values.
       
    66 */
       
    67 void CFileWriter::ConstructL()
       
    68     {
       
    69 	//LOG_MSG("->CFileWriter::ConstructL()\n");
       
    70     TInt err;
       
    71 
       
    72 	_LIT(KPluginDescription, "Symbian Elf Core Dump Writer");
       
    73 	iDescription = KPluginDescription().AllocL();
       
    74     iFs.Connect();
       
    75     iFs.ShareAuto(); //share the session with the crash processing thread
       
    76 
       
    77 	iConfigList.ReserveL( (TInt)EDataSaveLastParam );
       
    78 
       
    79 	COptionConfig *config;
       
    80 
       
    81 	_LIT( KFilePathPrompt, "Please supply Full Core Dump Filepath (eg \"C:\\coredump.core\")" );
       
    82 	config = COptionConfig::NewL(  (TInt)ECoreFilePath,
       
    83 									KFileWriterUid,								// UID, unused
       
    84 									COptionConfig::EWriterPlugin,
       
    85 									COptionConfig::ETFileName,
       
    86 									KFilePathPrompt,
       
    87                                     1,
       
    88 									KNullDesC,
       
    89 									0,
       
    90 									KNullDesC );
       
    91 
       
    92 	err = iConfigList.Append( config );
       
    93     if(err != KErrNone)
       
    94         {
       
    95 	    LOG_MSG2("CFileWriter::ConstructL - unable to append the param! err:%d\n", err);
       
    96         delete config;
       
    97         User::Leave(err);
       
    98         }
       
    99     }
       
   100 
       
   101 /**
       
   102 dtor frees config parameter list, plugin description descriptor and closes file server session.
       
   103 */
       
   104 CFileWriter::~CFileWriter()
       
   105     {
       
   106     iConfigList.ResetAndDestroy();
       
   107 	delete iDescription;
       
   108 	iFs.Close();
       
   109     }
       
   110 
       
   111 /**
       
   112 Returns a description of the plugin.
       
   113 @param aPluginDescription Output parameter that contains the plugin description.
       
   114 */
       
   115 void CFileWriter::GetDescription( TDes & aPluginDescription )
       
   116     {
       
   117 	aPluginDescription = *iDescription;
       
   118     }
       
   119 
       
   120 /**
       
   121 Called by CDS to ask for the configuration parameters that the writer implements.
       
   122 @return actual number of implemented config parameters
       
   123 */
       
   124 TInt CFileWriter::GetNumberConfigParametersL()
       
   125 	{
       
   126 	//LOG_MSG2("CFileWriter::GetNumberConfigParametersL()\n", iConfigList.Count() );
       
   127 	return iConfigList.Count();
       
   128 	}
       
   129 
       
   130 /**
       
   131 Called by CDS to ask for configuration parameter.
       
   132 @param aIndex indicates which parameter to return
       
   133 @return pointer to COptionConfig object representing the requested config parameter. Caller doesn't take ownership of the object!
       
   134 @leave KErrBadHandle if index is out of bounds
       
   135 @see COptionConfig
       
   136 */
       
   137 COptionConfig * CFileWriter::GetConfigParameterL( const TInt aIndex )
       
   138 	{
       
   139 	// return the config identified by aIndex
       
   140 	if( ( aIndex < 0 ) || ( aIndex >= iConfigList.Count() ) )
       
   141 		{
       
   142 		User::Leave( KErrBadHandle );
       
   143 		}
       
   144 
       
   145     return iConfigList[aIndex];
       
   146 	}
       
   147 
       
   148 /**
       
   149 Change a configuration parameter.
       
   150 @param aIndex Index of parameter to change
       
   151 @param aValue Unused
       
   152 @param aDescValue Path and filename to use
       
   153 @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
       
   154 */
       
   155 void CFileWriter::SetConfigParameterL( const TInt aIndex, const TInt32 & aValue, const TDesC & aDescValue )
       
   156     {
       
   157 	// Make the changes to our internal structures, and reflect such changes in our behaviour
       
   158 	if( ( aIndex < 0 ) || ( aIndex > iConfigList.Count() ) )
       
   159 		{
       
   160 		LOG_MSG2("CFileWriter::SetConfigParameterL - bad param request %d", aIndex );
       
   161 		User::Leave( KErrBadHandle );
       
   162 		}
       
   163 
       
   164 	COptionConfig & config = *(iConfigList[aIndex]);
       
   165 	if( aIndex == (TInt)ECoreFilePath )
       
   166 		{
       
   167 		if( iFs.IsValidName( aDescValue ) || aDescValue == KNullDesC )
       
   168 			{
       
   169 			config.ValueL( aDescValue );
       
   170 			}
       
   171 		else
       
   172 			{
       
   173 			_LIT( KInvalidFileErrorMsg ,"File Writer Error : Filepath Not Valid");
       
   174 			User::InfoPrint( KInvalidFileErrorMsg );
       
   175 			LOG_MSG(" CFileWriter::SetConfigParameterL() : ERROR  from RFs.IsValidName( )" );
       
   176 			User::Leave( KErrBadName );
       
   177 			}
       
   178 		}
       
   179 	else
       
   180 		{
       
   181 		LOG_MSG2("CFileWriter::SetConfigParameterL - invalid aIndex:%d\n", aIndex );
       
   182 		User::Leave( KErrBadHandle );
       
   183 		}
       
   184 
       
   185 	//If the descriptor is not null ensure it is a valid path
       
   186 	if(aDescValue != KNullDesC)
       
   187 		{
       
   188 		TParse parseName;
       
   189 		TInt err = parseName.Set( aDescValue, NULL, NULL );
       
   190 		if( KErrNone != err )
       
   191 			{
       
   192 			_LIT( KParseFileErrorMsg ,"File Writer Error : Could not Parse Filepath");
       
   193 			User::InfoPrint( KParseFileErrorMsg );
       
   194 			LOG_MSG(" CFileWriter::SetConfigParameterL() : ERROR  from TParse.Set( )" );
       
   195 			User::Leave( err );
       
   196 			}
       
   197 
       
   198 		TPtrC drvpath = parseName.DriveAndPath();
       
   199 		RDir rDir;
       
   200 		TInt dirErr = rDir.Open( iFs, drvpath, EFileWrite );
       
   201 		rDir.Close();
       
   202 		if( KErrNone != dirErr )
       
   203 			{
       
   204 			_LIT( KInvalidDirErrorMsg ,"File Writer Error : Directory Does Not Exist");
       
   205 			User::InfoPrint( KInvalidDirErrorMsg );
       
   206 			LOG_MSG2(" CFileWriter::SetConfigParameterL() : ERROR  from RDir.Open() returned %d", dirErr );
       
   207 			User::Leave( KErrBadName );
       
   208 			}
       
   209 		}
       
   210 
       
   211 	//This is initially the filename we intend to, and will try to use
       
   212 	iFileName = aDescValue;
       
   213     }
       
   214 
       
   215 /**
       
   216 Called by formatter to start the creation of a dump file.
       
   217 Can be called several times to create several files.
       
   218 Note that if the file specified either in the parameter here
       
   219 or the configuration already exists, the file writer will not 
       
   220 overwrite it, and instead just append a number in brackets to 
       
   221 the stem of the filename. e.g. e:\file(1).elf if e:\file.elf
       
   222 already exists. To determine the actual name used, call GetMediaName
       
   223 
       
   224 @see GetMediaName()
       
   225 @param aFileName Formatters can supply a file name to use
       
   226 @return one of the system error codes
       
   227 @leave err one of the system wide error codes
       
   228 */
       
   229 void CFileWriter::OpenL( const TDesC& aFileName )
       
   230     {
       
   231     User::LeaveIfError(Open(aFileName));
       
   232     }
       
   233 
       
   234 /**
       
   235 Called by formatter to start the creation of a dump file.
       
   236 Can be called several times to create several files.
       
   237 Note that if the file specified either in the parameter here
       
   238 or the configuration already exists, the file writer will not 
       
   239 overwrite it, and instead just append a number in brackets to 
       
   240 the stem of the filename. e.g. e:\file(1).elf if e:\file.elf
       
   241 already exists. To determine the actual name used, call GetMediaName
       
   242 
       
   243 @see GetMediaName()
       
   244 @param aFileName Formatters can supply a file name to use
       
   245 @return one of the system error codes
       
   246 */
       
   247 TInt CFileWriter::Open( const TDesC& aFileName )
       
   248 	{
       
   249     if(aFileName.Length() > 0)
       
   250         {
       
   251 		iFileName = aFileName;
       
   252         }
       
   253     else
       
   254         {
       
   255 		COptionConfig & config = *(iConfigList[ (TInt)ECoreFilePath ]);
       
   256 		iFileName = config.ValueAsDesc();
       
   257 	    }
       
   258 
       
   259 	LOG_MSG2("->CFileWriter::Open([%S])\n", &TPtr8((TUint8*)iFileName.Ptr(), 2*iFileName.Length(),	2*iFileName.Length() ));
       
   260 
       
   261 	//If the file exists already, we want to preserve it, and append a (%d) to the name of the new file
       
   262 	const TUint startAppend = 1;
       
   263 	TUint currentAppend = startAppend;
       
   264 	TBuf<KMaxFileName> formatString;
       
   265 
       
   266 	_LIT(KFormatString, "(%d)");
       
   267 	_LIT(KFileBackSlash, "\\");
       
   268 
       
   269 	for(;;)
       
   270 		{
       
   271 		//If file doesn't exist, we can use this name
       
   272 		if(!BaflUtils::FileExists(iFs, iFileName))
       
   273 			break;
       
   274 
       
   275 		//otherwise, we sort out the filename
       
   276 		if(currentAppend == startAppend)
       
   277 			{
       
   278 			//first time so it needs the (%d) at the end of the name
       
   279 			TParse p;
       
   280 			p.Set(iFileName, NULL, NULL);
       
   281 
       
   282 			formatString.Append(p.Drive());
       
   283 			formatString.Append(KFileBackSlash);
       
   284 			formatString.Append(p.Name());
       
   285 			formatString.Append(KFormatString);
       
   286 			formatString.Append(p.Ext());
       
   287 			}
       
   288 
       
   289 		iFileName.Format(formatString, currentAppend);
       
   290 		++currentAppend;
       
   291 		}
       
   292 
       
   293 	return iFile.Create(iFs, iFileName, EFileWrite);
       
   294     }
       
   295 
       
   296 /**
       
   297 This returns a reference to a descriptor containing the name
       
   298 of the file that the filewriter intends to use at any point 
       
   299 in time. Note that the filewriter will not determine what file
       
   300 to use until the last moment and so this is not gauranteed to 
       
   301 be the actual filename used until one of the Open() methods are
       
   302 called
       
   303 
       
   304 @see Open(const TDesC& aFileName)
       
   305 @see OpenL(const TDesC& aFileName)
       
   306 @return TDesC& reference to filename
       
   307 */
       
   308 const TDesC& CFileWriter::GetMediaName()
       
   309 	{
       
   310 	return iFileName;	
       
   311 	}
       
   312 
       
   313 /**
       
   314 Called by formatter at the end of the creation of a dump.
       
   315 Open() and Close() must be paired calls
       
   316 @pre Must have called Open() or OpenL()
       
   317 @leave err one of the system wide error codes
       
   318 */
       
   319 void CFileWriter::CloseL()
       
   320     {
       
   321 	User::LeaveIfError(Close());
       
   322     }
       
   323 
       
   324 /**
       
   325 Called by formatter at the end of the creation of a dump.
       
   326 Open() and Close() must be paired calls
       
   327 @return one of the system wide error codes
       
   328 */
       
   329 TInt CFileWriter::Close()
       
   330     {
       
   331     TInt err = iFile.Flush();
       
   332     //LOG_MSG2("->CFileWriter::Close() : returns:%d\n", err);
       
   333     iFile.Close();
       
   334 	return err;
       
   335     }
       
   336 
       
   337 /**
       
   338 Save binary aData
       
   339 
       
   340 @param aData Binary data to save
       
   341 @leave err one of the system wide error codes
       
   342 */
       
   343 void CFileWriter::WriteL( const TDesC8& aData )
       
   344     {
       
   345     User::LeaveIfError(Write(aData));
       
   346     }
       
   347 
       
   348 /**
       
   349 Save binary aData
       
   350 
       
   351 @param aData Binary data to save
       
   352 @return one of the system wide error codes
       
   353 */
       
   354 TInt CFileWriter::Write( const TDesC8& aData )
       
   355     {
       
   356     TInt err = iFile.Write(aData);
       
   357     if( KErrNone != err )
       
   358 		{
       
   359 		LOG_MSG2("CFileWriter::Write() : iFile.Write(aData) returned :%d\n", err);
       
   360 		}
       
   361     return err;
       
   362     }
       
   363 
       
   364 /**
       
   365 Save aSize bytes of binary data.
       
   366 
       
   367 @param aData Binary data to save
       
   368 @param aSize Number of bytes to save
       
   369 @leave err one of the system wide error codes
       
   370 */
       
   371 void CFileWriter::WriteL( TAny* aData, TUint aSize )
       
   372     {
       
   373     User::LeaveIfError(Write(aData, aSize));
       
   374     }
       
   375 
       
   376 /**
       
   377 Save aSize bytes of binary data
       
   378 
       
   379 @param aData Binary data to save
       
   380 @param aSize Number of bytes to save
       
   381 @return one of the system wide error codes
       
   382 */
       
   383 TInt CFileWriter::Write( TAny* aData, TUint aSize )
       
   384     {
       
   385     //LOG_MSG2("->CFileWriter::Writer(size=%d)\n", aSize);
       
   386     if(aData == NULL)
       
   387 		{
       
   388 		LOG_MSG2("CFileWriter::Writer(size=%d), aData == NULL\n", aSize);
       
   389         return KErrBadHandle;
       
   390 		}
       
   391 
       
   392     TPtrC8 data(static_cast<TUint8*>(aData), aSize);
       
   393     return( Write(data) );
       
   394     }
       
   395 
       
   396 /**
       
   397 Save all of aData to file. Leaves if error.
       
   398 
       
   399 @param aPos Input : Position to write to, in bytes.
       
   400 @param aData Input : Data to write to file
       
   401 @leave err one of the system wide error codes
       
   402 @see RFile
       
   403 */
       
   404 void CFileWriter::WriteL( TInt aPos, const TDesC8& aData )
       
   405     {
       
   406     User::LeaveIfError(Write(aPos, aData));
       
   407     }
       
   408 
       
   409 /**
       
   410 Save all of aData to file.
       
   411 Note that if a position beyond the end of the file is specified,
       
   412 then the write operation begins at the end of the file.
       
   413 Thus aPos must be within the file written so far. For example
       
   414 writing at position 10 when that position has no data yet will
       
   415 result in the data being written at the end of the current file.
       
   416 This is a limitation of RFile.
       
   417 
       
   418 @param aPos Input : Position to write to, in bytes.
       
   419 @param aData Input : Data to write to file
       
   420 @return Returns error from RFile::Write()
       
   421 @see RFile
       
   422 */
       
   423 TInt CFileWriter::Write( TInt aPos, const TDesC8& aData )
       
   424     {
       
   425 //	LOG_MSG2("  iFile.Write(aPos=%d, aData)\n", aPos );
       
   426     TInt err = iFile.Write(aPos, aData);
       
   427     if( KErrNone != err )
       
   428 		{
       
   429  		LOG_MSG3("CFileWriter::Write() : iFile.Write(aPos=%d, aData) returned :%d\n", aPos, err );
       
   430 		}
       
   431 
       
   432     return err;
       
   433     }
       
   434 
       
   435 /**
       
   436 Save aSize bytes of aData at file position aPos.
       
   437 Note that if a position beyond the end of the file is specified,
       
   438 then the write operation begins at the end of the file.
       
   439 Thus aPos must be within the file written so far. For example
       
   440 writing at position 10 when that position has no data yet will
       
   441 result in the data being written at the end of the current file.
       
   442 This is a limitation of RFile.
       
   443 
       
   444 @param aPos Input : Position to write to, in bytes.
       
   445 @param aData Input : Data to write to file
       
   446 @param aSize Input : Number of bytes to write
       
   447 @leave err one of the system wide error codes
       
   448 @see RFile
       
   449 */
       
   450 void CFileWriter::WriteL( TInt aPos, TAny* aData, TUint aSize )
       
   451     {
       
   452     User::LeaveIfError(Write(aPos, aData, aSize));
       
   453     }
       
   454 
       
   455 /**
       
   456 Save aSize bytes of aData at file position aPos.
       
   457 Note that if a position beyond the end of the file is specified,
       
   458 then the write operation begins at the end of the file.
       
   459 Thus aPos must be within the file written so far. For example
       
   460 writing at position 10 when that position has no data yet will
       
   461 result in the data being written at the end of the current file.
       
   462 This is a limitation of RFile.
       
   463 
       
   464 @param aPos Input : Position to write to, in bytes.
       
   465 @param aData Input : Data to write to file
       
   466 @param aSize Input : Number of bytes to write
       
   467 @return one of the system wide error codes
       
   468 @see RFile
       
   469 */
       
   470 TInt CFileWriter::Write( TInt aPos, TAny* aData, TUint aSize )
       
   471     {
       
   472     if(aData == NULL)
       
   473         {
       
   474 		LOG_MSG3("CFileWriter::Writer(pos=%d, size=%d), aData == NULL\n", aPos, aSize);
       
   475         return KErrNoMemory;
       
   476         }
       
   477 
       
   478     TPtrC8 data(static_cast<TUint8*>(aData), aSize);
       
   479     return( Write(aPos, data) );
       
   480     }