imgtools/romtools/rofsbuild/r_obey.cpp
changeset 0 044383f39525
child 590 360bd6b35136
child 606 30b30f9da0b7
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "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 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * @internalComponent * @released
       
    16 * Rofsbuild Obey file class and its reader class.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include <string.h>
       
    22 
       
    23 #ifdef __VC32__
       
    24  #ifdef __MSVCDOTNET__
       
    25   #include <strstream>
       
    26   #include <iomanip>
       
    27  #else //__MSVCDOTNET__
       
    28   #include <strstrea.h>
       
    29   #include <iomanip.h>
       
    30  #endif  //__MSVCDOTNET__
       
    31 #else // !__VC32__
       
    32 #ifdef __TOOLS2__
       
    33 	#include <sstream>
       
    34 	#include <iomanip>
       
    35 	#include <sys/stat.h>
       
    36 	using namespace std;
       
    37 #else
       
    38 	#include <strstrea.h>
       
    39 	#include <iomanip.h>
       
    40 #endif
       
    41  
       
    42 #endif //__VC32__
       
    43 
       
    44 
       
    45 #include <stdlib.h>
       
    46 #include <stdio.h>
       
    47 #include <time.h>
       
    48 #include <assert.h>
       
    49 #include <errno.h>
       
    50 
       
    51 #include <e32std.h>
       
    52 #include <e32std_private.h>
       
    53 #include <e32rom.h>
       
    54 #include <u32std.h>
       
    55 #include <f32file.h>
       
    56 
       
    57 #include "h_utl.h"
       
    58 #include "r_obey.h"
       
    59 #include "r_coreimage.h"
       
    60 #include "patchdataprocessor.h"
       
    61 #include "filesysteminterface.h" 
       
    62 #include "r_driveimage.h"
       
    63 
       
    64 extern TInt gCodePagingOverride;
       
    65 extern TInt gDataPagingOverride;
       
    66 extern ECompression gCompress;
       
    67 extern TBool gEnableStdPathWarning; // Default to not warn if destination path provided for a file is not in standard path.
       
    68 
       
    69 
       
    70 
       
    71 #define _P(word)	word, sizeof(word)-1	// match prefix, optionally followed by [HWVD]
       
    72 #define _K(word)	word, 0					// match whole word
       
    73 
       
    74 const ObeyFileKeyword ObeyFileReader::iKeywords[] =
       
    75 {
       
    76 	{_K("file"),		2,-2, EKeywordFile, "File to be copied into ROFS"},
       
    77 	{_K("data"),		2,-2, EKeywordData, "same as file"},
       
    78 
       
    79 	{_K("rofsname"),	1, 1, EKeywordRofsName, "output file for ROFS image"},
       
    80 	{_K("romsize"),		1, 1, EKeywordRomSize, "size of ROM image"}, 
       
    81 	{_P("hide"),	    2, -1, EKeywordHide, "Exclude named file from ROM directory structure"},
       
    82 	{_P("alias"),	    2, -2, EKeywordAlias, "Create alias for existing file in ROM directory structure"},
       
    83 	{_P("rename"),	    2, -2, EKeywordRename, "Change the name of a file in the ROM directory structure"},
       
    84 	{_K("rofssize"),		1, 1, EKeywordRofsSize, "maximum size of ROFS image"},
       
    85 	{_K("romchecksum"),	1, 1, EKeywordRofsChecksum, "desired 32-bit checksum value for the whole image"},
       
    86 	{_K("version"),		1, 1, EKeywordVersion, "ROFS image version number"},
       
    87 	{_K("time"),	    1,-1, EKeywordTime, "ROFS image timestamp"},
       
    88 	{_K("extensionrofs"),1+2, 1, EKeywordExtensionRofs, "Start of definition of optional Extension ROFS"},
       
    89 	{_K("extensionrofsname"),1, 1, EKeywordCoreRofsName, "ROFS image on which extension ROFS is based"},
       
    90 	{_K("rem"),			0, 0, EKeywordNone, "comment"},
       
    91 	{_K("stop"),		0, 0, EKeywordNone, "Terminates OBEY file prematurely"},
       
    92 	{_K("romchecksum"),	1, 1, EKeywordRomChecksum, "desired 32-bit checksum value for the whole ROFS image"},
       
    93 	{_K("coreimage"),	1, 1, EKeywordCoreImage, "Core image to be used for extension directory structure"},
       
    94 	{_K("autosize"),	1, 1, EKeywordRofsAutoSize, "Automatically adjust maximum image size to actual used"},
       
    95 	{_K("pagingoverride"),	1, 1, EKeywordPagingOverride, "Overide the demand paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
    96 	{_K("codepagingoverride"),	1, 1, EKeywordCodePagingOverride, "Overide the code paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
    97 	{_K("datapagingoverride"),	1, 1, EKeywordDataPagingOverride, "Overide the data paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
    98 	{_K("dataimagename"),1, 1,EKeywordDataImageName, "Data Drive image file name"},
       
    99 	{_K("dataimagefilesystem"),1, 1,EKeywordDataImageFileSystem, "Drive image file system format"},
       
   100 	{_K("dataimagesize"),1, 1,EKeywordDataImageSize, "Maximum size of Data Drive image"},
       
   101 	{_K("volume"),1, -1,EKeywordDataImageVolume, "Volume Label of Data Drive image"},
       
   102 	{_K("sectorsize"),1, 1,EKeywordDataImageSectorSize, "Sector size(in bytes) of Data Drive image"},
       
   103 	{_K("fattable"),1, 1,EKeywordDataImageNoOfFats, "Number of FATs in the Data Drive image"},
       
   104 	// things we don't normally report in the help information
       
   105 	{_K("trace"),		1, 1, EKeywordTrace, "(ROMBUILD activity trace flags)"},
       
   106 	{_K("filecompress"),2, -2,EKeywordFileCompress,"Non-XIP Executable to be loaded into the ROM compressed" },
       
   107 	{_K("fileuncompress"),2, -2,EKeywordFileUncompress,"Non-XIP Executable to be loaded into the ROM uncompressed" },
       
   108 	{_K("patchdata"),2, 5,EKeywordPatchDllData, "Patch exported data"},
       
   109 	{_K("imagename"), 1, 1, EKeywordSmrImageName, "output file for SMR image"},
       
   110 	{_K("hcrdata"), 1, 1, EKeywordSmrFileData, "file data for HCR SMR image"},
       
   111 	{_K("formatversion"), 1, 1, EKeywordSmrFormatVersion, "format version for HCR SMR image"},
       
   112 	{_K("payloadflags"), 1, 1, EKeywordSmrFlags, "payload flags for the HCR SMR image"},
       
   113 	{_K("payloaduid"), 1, 1, EKeywordSmrUID, "payload UID for the HCR SMR image"},
       
   114 	{0,0,0,0,EKeywordNone,""}
       
   115 };
       
   116 
       
   117 extern TInt isNumber(TText *aString);
       
   118 extern TInt getNumber(TText *aStr);
       
   119 
       
   120 void ObeyFileReader::KeywordHelp() // static
       
   121 	{
       
   122 	cout << "Obey file keywords:\n";
       
   123 
       
   124 	const ObeyFileKeyword* k=0;
       
   125 	for (k=iKeywords; k->iKeyword!=0; k++)
       
   126 		{
       
   127 		if (k->iHelpText==0)
       
   128 			continue;
       
   129 		if (k->iHelpText[0]=='(' && !H.iVerbose)
       
   130 			continue;	// don't normally report things in (parentheses)
       
   131 
       
   132 		char buf[32];
       
   133 		sprintf(buf, "%-20s", k->iKeyword);
       
   134 		if (k->iKeywordLength)
       
   135 			memcpy(buf+k->iKeywordLength,"[HWVD]",6);
       
   136 		if (H.iVerbose)
       
   137 			sprintf(buf+20,"%2d",k->iNumArgs);
       
   138 		cout << "    " << buf << " " << k->iHelpText << endl;
       
   139 		}
       
   140 	cout << endl;
       
   141 
       
   142 	cout << "File attributes:\n";
       
   143 
       
   144 	const FileAttributeKeyword* f=0;
       
   145 	for (f=iAttributeKeywords; f->iKeyword!=0; f++)
       
   146 		{
       
   147 		if (f->iHelpText==0)
       
   148 			continue;
       
   149 		if (f->iHelpText[0]=='(' && !H.iVerbose)
       
   150 			continue;	// don't normally report things in (parentheses)
       
   151 
       
   152 		char buf[32];
       
   153 		sprintf(buf, "%-20s", f->iKeyword);
       
   154 		if (H.iVerbose)
       
   155 			sprintf(buf+20,"%2d",k->iNumArgs);
       
   156 		cout << "    " << buf << " " << f->iHelpText << endl;
       
   157 		}
       
   158 	cout << endl;
       
   159 	}
       
   160 
       
   161 ObeyFileReader::ObeyFileReader(TText* aFileName):
       
   162 iObeyFile(0),iMark(0), iMarkLine(0), iCurrentMark(0), iCurrentLine(0), imaxLength(0)
       
   163 	{
       
   164 
       
   165 	iFileName = new TText[strlen((const char *)aFileName)+1];
       
   166 	strcpy((char *)iFileName,(const char *)aFileName);
       
   167 	iNumWords = 0 ;
       
   168 	for(unsigned int i = 0 ; i < KNumWords ; i++)
       
   169 		iWord[i] = 0 ;
       
   170 	iSuffix = new TText();
       
   171 	iLine = 0 ;
       
   172 	iCurrentObeyStatement = 0 ;
       
   173 	 }
       
   174 
       
   175 
       
   176 ObeyFileReader::~ObeyFileReader()
       
   177 	{
       
   178 	if (iObeyFile)
       
   179 		fclose(iObeyFile);
       
   180 	iObeyFile=0;
       
   181 	delete [] iFileName;
       
   182 	delete [] iLine;
       
   183 	delete [] iCurrentObeyStatement;
       
   184 	}
       
   185 
       
   186 TBool ObeyFileReader::Open()
       
   187 //
       
   188 // Open the file & return a status
       
   189 //
       
   190 {
       
   191     if (!iFileName)
       
   192     {
       
   193         return EFalse;
       
   194     }
       
   195 
       
   196     iObeyFile = fopen((const char *)iFileName,"r");
       
   197     if (!iObeyFile)
       
   198     {
       
   199         Print(EError,"Cannot open obey file %s\n",iFileName);
       
   200         return EFalse;
       
   201     }
       
   202     if (SetLineLengthBuffer() != KErrNone)
       
   203     {
       
   204         Print(EError,"Insufficent Memory to Continue.");	
       
   205         return EFalse;
       
   206     }
       
   207     return ETrue;
       
   208 }
       
   209    
       
   210  TInt ObeyFileReader::SetLineLengthBuffer()
       
   211  // Get the Max Line length for the given obey file and allocate the buffer.
       
   212  	{
       
   213 	char ch = '\0';
       
   214  	TInt length = 0;
       
   215 		
       
   216 	Rewind();
       
   217  	while ((ch = (char)fgetc(iObeyFile)) != EOF)
       
   218  		{
       
   219  		length++;
       
   220 		if (ch == '\n')
       
   221 			{
       
   222  			if (length > imaxLength)
       
   223  				imaxLength = length;
       
   224  			length = 0;				
       
   225  			}
       
   226  		}
       
   227 	
       
   228 	if (length > imaxLength)
       
   229  		imaxLength = length;
       
   230 		
       
   231 	if (0 == imaxLength)
       
   232 		{
       
   233 		Print(EError,"Empty obey file passed as input.");
       
   234 		exit(-1);
       
   235 		}			
       
   236 	else if (imaxLength < 2)
       
   237 		{
       
   238 		Print(EError,"Invalid obey file passed as input.");
       
   239 		exit(-1);
       
   240 		}
       
   241 		
       
   242 	Rewind();
       
   243  	iLine = new TText[imaxLength+1];
       
   244  	
       
   245  	if(!iLine)
       
   246  		return KErrNoMemory;
       
   247  
       
   248  	return KErrNone;
       
   249  	}
       
   250 
       
   251 void ObeyFileReader::Mark()
       
   252 	{
       
   253 
       
   254 	iMark = iCurrentMark;
       
   255 	iMarkLine = iCurrentLine-1;
       
   256 	}
       
   257 
       
   258 void ObeyFileReader::MarkNext()
       
   259 	{
       
   260 
       
   261 	iMark = ftell(iObeyFile);
       
   262 	iMarkLine = iCurrentLine;
       
   263 	}
       
   264 
       
   265 void ObeyFileReader::Rewind()
       
   266 	{
       
   267 	
       
   268 	fseek(iObeyFile,iMark,SEEK_SET);
       
   269 	iCurrentMark = iMark;
       
   270 	iCurrentLine = iMarkLine;
       
   271 	}
       
   272 
       
   273 void ObeyFileReader::CopyWord(TInt aIndex, TText*& aString)
       
   274 	{
       
   275 	aString = new TText[strlen((const char *)iWord[aIndex])+1];
       
   276 	strcpy((char *)aString, (const char *)iWord[aIndex]);
       
   277 	}
       
   278 
       
   279 TInt ObeyFileReader::ReadAndParseLine()
       
   280 	{
       
   281 	if (feof(iObeyFile))
       
   282 		return KErrEof;
       
   283 	iCurrentLine++;
       
   284 	iCurrentMark = ftell(iObeyFile);
       
   285 	iLine[0]='\0';
       
   286 	fgets((char*)iLine,imaxLength+1,iObeyFile);
       
   287 	iCurrentObeyStatement = new TText[imaxLength+1];
       
   288 	strcpy((char*)iCurrentObeyStatement,(char*)iLine);
       
   289 	iNumWords = Parse();
       
   290 	return KErrNone;
       
   291 	}
       
   292 
       
   293 TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword)
       
   294 	{
       
   295 
       
   296 NextLine:
       
   297 	TInt err = ReadAndParseLine();
       
   298 	if (err == KErrEof)
       
   299 		return KErrEof;
       
   300 	if (iNumWords == 0 || stricmp((const char*)iWord[0], "rem")==0)
       
   301 		goto NextLine;
       
   302 	if (stricmp((const char*)iWord[0], "stop")==0)
       
   303 		return KErrEof;
       
   304 
       
   305 	const ObeyFileKeyword* k=0;
       
   306 	for (k=iKeywords; k->iKeyword!=0; k++)
       
   307 		{
       
   308 		if (k->iKeywordLength == 0)
       
   309 			{
       
   310 			// Exact case-insensitive match on keyword
       
   311 			if (stricmp((const char*)iWord[0], k->iKeyword) != 0)
       
   312 				continue;
       
   313 			iSuffix = 0;
       
   314 			}
       
   315 		else
       
   316 			{
       
   317 			// Prefix match
       
   318 			if (strnicmp((const char*)iWord[0], k->iKeyword, k->iKeywordLength) != 0)
       
   319 				continue;
       
   320 			// Suffix must be empty, or a variant number in []
       
   321 			iSuffix = iWord[0]+k->iKeywordLength;
       
   322 			if (*iSuffix != '\0' && *iSuffix != '[')
       
   323 				continue;
       
   324 			}
       
   325 		// found a match
       
   326 		if ((k->iPass & aPass) == 0)
       
   327 			goto NextLine;
       
   328 		if (k->iNumArgs>=0 && (1+k->iNumArgs != iNumWords))
       
   329 			{
       
   330 			Print(EError, "Incorrect number of arguments for keyword %s on line %d.\n",
       
   331 				iWord[0], iCurrentLine);
       
   332 			goto NextLine;
       
   333 			}
       
   334 		if (k->iNumArgs<0 && (1-k->iNumArgs > iNumWords))
       
   335 			{
       
   336 			Print(EError, "Too few arguments for keyword %s on line %d.\n",
       
   337 				iWord[0], iCurrentLine);
       
   338 			goto NextLine;
       
   339 			}
       
   340 		
       
   341 		aKeyword = k->iKeywordEnum;
       
   342 		return KErrNone;
       
   343 		}
       
   344 	if (aPass == 1)
       
   345 		Print(EWarning, "Unknown keyword '%s'.  Line %d ignored\n", iWord[0], iCurrentLine);
       
   346 	goto NextLine;
       
   347 	}
       
   348 
       
   349 inline TBool ObeyFileReader::IsGap(char ch)
       
   350 	{
       
   351 	return (ch==' ' || ch=='=' || ch=='\t');
       
   352 	}
       
   353 
       
   354 TInt ObeyFileReader::Parse()
       
   355 //
       
   356 // splits a line into words, and returns the number of words found
       
   357 //
       
   358 	{
       
   359 
       
   360 	TInt i;
       
   361 	TText *letter=iLine;
       
   362 	TText *end=iLine+strlen((char *)iLine);
       
   363 	for (i=0; (TUint)i<KNumWords; i++)
       
   364 		iWord[i]=end;
       
   365 
       
   366 	enum TState {EInWord, EInQuotedWord, EInGap};
       
   367 	TState state=EInGap;
       
   368 
       
   369 	i=0;
       
   370 	while ((TUint)i<KNumWords && letter<end)
       
   371 		{
       
   372 		char ch=*letter;
       
   373 		if (ch==0)
       
   374 			break;
       
   375 		if (ch=='\n')
       
   376 			{
       
   377 			*letter='\0';	// remove trailing newline left by fgets
       
   378 			break;
       
   379 			}
       
   380 		switch (state)
       
   381 			{
       
   382 		case EInGap:
       
   383 			if (ch=='\"')
       
   384 				{
       
   385 				if (letter[1]!=0 && letter[1]!='\"')
       
   386 					iWord[i++]=letter+1;
       
   387 				state=EInQuotedWord;
       
   388 				}
       
   389 			else if (!IsGap(ch))
       
   390 				{
       
   391 				iWord[i++]=letter;
       
   392 				state=EInWord;
       
   393 				}
       
   394 			else
       
   395 				*letter=0;
       
   396 			break;
       
   397 		case EInWord:
       
   398 			if (ch=='\"')
       
   399 				{
       
   400 				*letter=0;
       
   401 				if (letter[1]!=0 && letter[1]!='\"')
       
   402 					iWord[i++]=letter+1;
       
   403 				state=EInQuotedWord;
       
   404 				}
       
   405 			else if (IsGap(ch))
       
   406 				{
       
   407 				*letter=0;
       
   408 				state=EInGap;
       
   409 				}
       
   410 			break;
       
   411 		case EInQuotedWord:
       
   412 			if (ch=='\"')
       
   413 				{
       
   414 				*letter=0;
       
   415 				state=EInGap;
       
   416 				}
       
   417 			break;
       
   418 			}
       
   419 		letter++;
       
   420 		}
       
   421 	return i;
       
   422 	}
       
   423 
       
   424 
       
   425 void ObeyFileReader::ProcessTime(TInt64& aTime)
       
   426 //
       
   427 // Process the timestamp
       
   428 //
       
   429 	{
       
   430 	char timebuf[256];
       
   431 	if (iNumWords>2)
       
   432 		sprintf(timebuf, "%s_%s", iWord[1], iWord[2]);
       
   433 	else
       
   434 		strcpy(timebuf, (char*)iWord[1]);
       
   435 
       
   436 	TInt r=StringToTime(aTime, timebuf);
       
   437 	if (r==KErrGeneral)
       
   438 		{
       
   439 		Print(EError, "incorrect format for time keyword on line %d\n", iCurrentLine);
       
   440 		exit(0x670);
       
   441 		}
       
   442 	if (r==KErrArgument)
       
   443 		{
       
   444 		Print(EError, "Time out of range on line %d\n", iCurrentLine);
       
   445 		exit(0x670);
       
   446 		}
       
   447 	}
       
   448 
       
   449 TInt64 ObeyFileReader::iTimeNow=0;
       
   450 void ObeyFileReader::TimeNow(TInt64& aTime)
       
   451 	{
       
   452 	if (iTimeNow==0)
       
   453 		{
       
   454 		TInt sysTime=time(0);					// seconds since midnight Jan 1st, 1970
       
   455 		sysTime-=(30*365*24*60*60+7*24*60*60);	// seconds since midnight Jan 1st, 2000
       
   456 		TInt64 daysTo2000AD=730497;
       
   457 		TInt64 t=daysTo2000AD*24*3600+sysTime;	// seconds since 0000
       
   458 		t=t+3600;								// BST (?)
       
   459 		iTimeNow=t*1000000;						// milliseconds
       
   460 		}
       
   461 	aTime=iTimeNow;
       
   462 	}
       
   463 
       
   464 /**
       
   465 Funtion to get the current oby file line
       
   466 */
       
   467 TText* ObeyFileReader::GetCurrentObeyStatement() const
       
   468 { 
       
   469 	return iCurrentObeyStatement;
       
   470 }
       
   471 
       
   472 // File attributes.
       
   473 
       
   474 
       
   475 const FileAttributeKeyword ObeyFileReader::iAttributeKeywords[] =
       
   476 {
       
   477 	{"attrib",3			,0,1,EAttributeAtt, "File attributes in ROM file system"},
       
   478 	{"exattrib",3		,0,1,EAttributeAttExtra, "File extra attributes in ROM file system"},
       
   479 //	{_K("compress")		,1,1,EAttributeCompress, "Compress file"},
       
   480 	{"stack",3			,1,1,EAttributeStack, "?"},
       
   481 	{"fixed",3			,1,0,EAttributeFixed, "Relocate to a fixed address space"},
       
   482 	{"priority",3		,1,1,EAttributePriority, "Override process priority"},
       
   483 	{_K("uid1")			,1,1,EAttributeUid1, "Override first UID"},
       
   484 	{_K("uid2")			,1,1,EAttributeUid2, "Override second UID"},
       
   485 	{_K("uid3")			,1,1,EAttributeUid3, "Override third UID"},
       
   486 	{_K("heapmin")		,1,1,EAttributeHeapMin, "Override initial heap size"},
       
   487 	{_K("heapmax")		,1,1,EAttributeHeapMax, "Override maximum heap size"},
       
   488 	{_K("capability")	,1,1,EAttributeCapability, "Override capabilities"},
       
   489 	{_K("unpaged")		,1,0,EAttributeUnpaged, "Don't page code or data for this file"},
       
   490 	{_K("paged")		,1,0,EAttributePaged, "Page code and data for this file"},
       
   491 	{_K("unpagedcode")	,1,0,EAttributeUnpagedCode, "Don't page code for this file"},
       
   492 	{_K("pagedcode")	,1,0,EAttributePagedCode, "Page code for this file"},
       
   493 	{_K("unpageddata")	,1,0,EAttributeUnpagedData, "Don't page data for this file"},
       
   494 	{_K("pageddata")	,1,0,EAttributePagedData, "Page data for this file"},
       
   495 	{0,0,0,0,EAttributeAtt,0}
       
   496 };
       
   497 
       
   498 TInt ObeyFileReader::NextAttribute(TInt& aIndex, TInt aHasFile, enum EFileAttribute& aKeyword, TText*& aArg)
       
   499 	{
       
   500 NextAttribute:
       
   501 	if (aIndex >= iNumWords)
       
   502 		return KErrEof;
       
   503 	TText* word=iWord[aIndex++];
       
   504 	const FileAttributeKeyword* k;
       
   505 	for (k=iAttributeKeywords; k->iKeyword!=0; k++)
       
   506 		{
       
   507 		if (k->iKeywordLength == 0)
       
   508 			{
       
   509 			// Exact match on keyword
       
   510 			if (stricmp((const char*)word, k->iKeyword) != 0)
       
   511 				continue;
       
   512 			}
       
   513 		else
       
   514 			{
       
   515 			// Prefix match
       
   516 			if (strnicmp((const char*)word, k->iKeyword, k->iKeywordLength) != 0)
       
   517 				continue;
       
   518 			}
       
   519 		// found a match
       
   520 		if (k->iNumArgs>0)
       
   521 			{
       
   522 			TInt argIndex = aIndex;
       
   523 			aIndex += k->iNumArgs;		// interface only really supports 1 argument
       
   524 			if (aIndex>iNumWords)
       
   525 				{
       
   526 				Print(EError, "Missing argument for attribute %s on line %d\n", word, iCurrentLine);
       
   527 				return KErrArgument;
       
   528 				}
       
   529 			aArg=iWord[argIndex];
       
   530 			}
       
   531 		if (k->iIsFileAttribute && !aHasFile)
       
   532 			{
       
   533 			Print(EError, "File attribute %s applied to non-file on line %d\n", word, iCurrentLine);
       
   534 			return KErrNotSupported;
       
   535 			}
       
   536 		aKeyword=k->iAttributeEnum;
       
   537 		return KErrNone;
       
   538 		}
       
   539 	Print(EWarning, "Unknown attribute '%s' skipped on line %d\n", word, iCurrentLine);
       
   540 	goto NextAttribute;
       
   541 	}
       
   542 
       
   543 
       
   544 
       
   545 /**
       
   546 Constructor:
       
   547 1.Obey file instance.
       
   548 2.used by both rofs and datadrive image.
       
   549 
       
   550 @param aReader - obey file reader object.
       
   551 */
       
   552 CObeyFile::CObeyFile(ObeyFileReader& aReader):
       
   553 	iRomFileName(NULL),
       
   554 	iExtensionRofsName(0),
       
   555 	iKernelRofsName(0),
       
   556 	iRomSize(0),
       
   557 	iVersion(0,0,0),
       
   558 	iCheckSum(0),
       
   559 	iNumberOfFiles(0),
       
   560 	iTime(0),
       
   561 	iRootDirectory(0),
       
   562 	iNumberOfDataFiles(0),
       
   563 	iDriveFileName(0),
       
   564 	iDataSize(0),
       
   565 	iDriveFileFormat(0),
       
   566 	iConfigurableFatAttributes(new ConfigurableFatAttributes),
       
   567 	iReader(aReader), 
       
   568 	iMissingFiles(0), 
       
   569 	iLastExecutable(0),
       
   570 	iFirstFile(0), 	
       
   571 	iCurrentFile(0),
       
   572 	iAutoSize(EFalse),
       
   573 	iAutoPageSize(4096),
       
   574 	iPagingOverrideParsed(0),
       
   575 	iCodePagingOverrideParsed(0),
       
   576 	iDataPagingOverrideParsed(0),
       
   577 	iPatchData(new CPatchDataProcessor)
       
   578 	{
       
   579 		iNextFilePtrPtr = &iFirstFile ;
       
   580 	}
       
   581 
       
   582 /**
       
   583 Obey file Destructor.
       
   584 1.Release the tree memory.
       
   585 2.Release all allocated memory if any.
       
   586 */
       
   587 CObeyFile::~CObeyFile()
       
   588 //
       
   589 // Destructor
       
   590 //
       
   591 	{
       
   592 	if(iDriveFileName)
       
   593 		delete[] iDriveFileName;					
       
   594 	if(iDriveFileFormat)
       
   595 		delete[] iDriveFileFormat;
       
   596 	iRootDirectory->deleteTheFirstNode();                
       
   597 	iRootDirectory->InitializeCount();
       
   598 
       
   599 	Release();
       
   600 	delete [] iRomFileName;
       
   601 	if (iRootDirectory)
       
   602 		iRootDirectory->Destroy();
       
   603 
       
   604 	delete iConfigurableFatAttributes;
       
   605 	delete iPatchData;
       
   606 	}
       
   607 
       
   608 TBool CObeyFile::AutoSize()
       
   609 {
       
   610 	return iAutoSize;
       
   611 }
       
   612 
       
   613 TUint32 CObeyFile::AutoPageSize()
       
   614 {
       
   615 	return iAutoPageSize;
       
   616 }
       
   617 
       
   618 void CObeyFile::Release()
       
   619 //
       
   620 // Free resources not needed after building a ROM
       
   621 //
       
   622 	{
       
   623 	iFirstFile = 0;
       
   624 	iNextFilePtrPtr = &iFirstFile;
       
   625 	}
       
   626 
       
   627 TRomBuilderEntry *CObeyFile::FirstFile()
       
   628 	{
       
   629 	iCurrentFile = iFirstFile;
       
   630 	return iCurrentFile;
       
   631 	}
       
   632 
       
   633 TRomBuilderEntry *CObeyFile::NextFile()
       
   634 	{
       
   635 	iCurrentFile = iCurrentFile ? iCurrentFile->iNext : 0;
       
   636 	return iCurrentFile;
       
   637 	}
       
   638 
       
   639 TText* CObeyFile::ProcessCoreImage()
       
   640 	{
       
   641 	// check for coreimage keyword and return filename
       
   642 	iReader.Rewind();
       
   643 	enum EKeyword keyword;
       
   644 	TText* coreImageFileName = 0;
       
   645 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   646 		{
       
   647 		  if (keyword == EKeywordCoreImage)
       
   648 			  {
       
   649   			  #if defined(__TOOLS2__) && defined (_STLP_THREADS)
       
   650   			  istringstream val(iReader.Word(1),(ios_base::in+ios_base::out));	  
       
   651   			  #elif __TOOLS2__
       
   652   			  istringstream val(iReader.Word(1),(std::_Ios_Openmode)(ios_base::in+ios_base::out));
       
   653 			  #else
       
   654 			  istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
   655 			  #endif
       
   656 			  iReader.CopyWord(1, coreImageFileName);
       
   657 			  iReader.MarkNext(); // ready for processing extension
       
   658 			  break;
       
   659 			  }
       
   660 		}
       
   661 	return coreImageFileName;
       
   662 	}
       
   663 
       
   664 void CObeyFile::SkipToExtension()
       
   665 	{
       
   666 	iReader.Rewind();
       
   667 	enum EKeyword keyword;
       
   668 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   669 		{
       
   670 		  if (keyword == EKeywordExtensionRofs)
       
   671 			  {
       
   672 			  iReader.Mark(); // ready for processing extension
       
   673 			  break;
       
   674 			  }
       
   675 		}
       
   676 	}
       
   677 TInt CObeyFile::ProcessRofs()
       
   678 	{
       
   679 	//
       
   680 	// First pass through the obey file to set up key variables
       
   681 	//
       
   682 
       
   683 	iReader.Rewind();
       
   684 
       
   685 	TInt count=0;
       
   686 	enum EKeyword keyword;
       
   687 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   688 		{
       
   689 		  if (keyword == EKeywordExtensionRofs)
       
   690 		    {
       
   691 		      if (count==0)
       
   692 			return KErrNotFound;		// no core ROFS, just extension ROFSs.
       
   693 		      break;
       
   694 		    }
       
   695 
       
   696 		count++;
       
   697 		if (! ProcessKeyword(keyword))
       
   698 			return KErrGeneral;
       
   699 		}
       
   700 
       
   701 	if (!GotKeyVariables())
       
   702 		return KErrGeneral;
       
   703 
       
   704 	//
       
   705 	// second pass to process the file specifications in the obey file building
       
   706 	// up the TRomNode directory structure and the TRomBuilderEntry list
       
   707 	//
       
   708 	iReader.Rewind();
       
   709 
       
   710 	iRootDirectory = new TRomNode((TText*)"");
       
   711 	iLastExecutable = iRootDirectory;
       
   712 
       
   713 	TInt align=0;
       
   714 	while (iReader.NextLine(2,keyword)!=KErrEof)
       
   715 		{
       
   716 		if (keyword == EKeywordExtensionRofs)
       
   717 			break;
       
   718 
       
   719 		if (keyword == EKeywordHide)
       
   720 			keyword = EKeywordHideV2;
       
   721 
       
   722 		switch (keyword)
       
   723 			{
       
   724 			  
       
   725 		case EKeywordHide:
       
   726 		case EKeywordAlias:
       
   727 		case EKeywordRename:
       
   728 			if (!ProcessRenaming(keyword))
       
   729 				return KErrGeneral;
       
   730 			break;
       
   731 		case EKeywordPatchDllData:
       
   732 		{
       
   733 			// Collect patchdata statements to process at the end
       
   734 			StringVector patchDataTokens;
       
   735 			SplitPatchDataStatement(patchDataTokens); 
       
   736 			iPatchData->AddPatchDataStatement(patchDataTokens);									
       
   737 			break;
       
   738 		}
       
   739 		default:
       
   740 		        if (!ProcessFile(align, keyword))
       
   741 		        return KErrGeneral;
       
   742 		        align=0;
       
   743 		        break;
       
   744 			}
       
   745 		}
       
   746 
       
   747 	if(!ParsePatchDllData())
       
   748 		return KErrGeneral;
       
   749 	iReader.Mark();			// ready for processing the extension rom(s)
       
   750 
       
   751 	if (iMissingFiles!=0)
       
   752 		{
       
   753 		return KErrGeneral;
       
   754 		}
       
   755 	if ( 0 == iNumberOfFiles )
       
   756 		{
       
   757 		Print(EError, "No files specified.\n");
       
   758 		return KErrGeneral;
       
   759 		}
       
   760 
       
   761 	return KErrNone;
       
   762 	}
       
   763 
       
   764 TBool CObeyFile::Process()
       
   765 {
       
   766 	TBool result = ETrue;
       
   767 	iReader.Rewind();
       
   768 	enum EKeyword keyword;
       
   769 	while(iReader.NextLine(1, keyword) != KErrEof)
       
   770 	{
       
   771 		String key = iReader.Word(0);
       
   772 		String value = iReader.Word(1);
       
   773 		if(iKeyValues.find(key) != iKeyValues.end())
       
   774 		{
       
   775 			iKeyValues[key].push_back(value);
       
   776 		}
       
   777 		else
       
   778 		{
       
   779 			StringVector values;
       
   780 			values.push_back(value);
       
   781 			iKeyValues[key]=values;
       
   782 		}
       
   783 
       
   784 
       
   785 	}
       
   786 	return result;
       
   787 }
       
   788 StringVector CObeyFile::getValues(const String& aKey)
       
   789 {
       
   790 	StringVector values;
       
   791 	if(iKeyValues.find(aKey) != iKeyValues.end())
       
   792 	{
       
   793 		values = iKeyValues[aKey];
       
   794 	}
       
   795 	return values;
       
   796 }
       
   797 
       
   798 /**
       
   799 Process drive obey file and construct the tree.
       
   800 
       
   801 @return - Return the status,
       
   802           'KErrnone' for Success,
       
   803           'KErrGeneral' for failure (required keywords not there in obey file or failed
       
   804 									 to construct the tree).
       
   805 */
       
   806 TInt CObeyFile::ProcessDataDrive()
       
   807 	{
       
   808 
       
   809 	iReader.Rewind();
       
   810 	enum EKeyword keyword;
       
   811 
       
   812 	// First pass through the obey file to set up key variables
       
   813 	while (iReader.NextLine(1,keyword) != KErrEof)	
       
   814 		{
       
   815 		if (!ProcessDriveKeyword(keyword))			
       
   816 			return KErrGeneral;
       
   817 		}
       
   818 
       
   819 	if (!GotKeyDriveVariables())
       
   820 		return KErrGeneral;
       
   821 
       
   822 	// Second pass to process the file specifications in the obey file.
       
   823 	// Build the TRomNode directory structure and the TRomBuilderEntry list
       
   824 	iReader.Rewind();
       
   825 	iRootDirectory = new TRomNode((TText*)"//");					
       
   826 	iLastExecutable = iRootDirectory;
       
   827 
       
   828 	while(iReader.NextLine(2,keyword)!=KErrEof)
       
   829 		{
       
   830 		switch (keyword)
       
   831 			{
       
   832 			case EKeywordPatchDllData:
       
   833 			{	// Collect patchdata statements to process at the end
       
   834 				StringVector patchDataTokens;
       
   835 				SplitPatchDataStatement(patchDataTokens); 				
       
   836 				iPatchData->AddPatchDataStatement(patchDataTokens);									
       
   837 				break;
       
   838 			}
       
   839 	
       
   840 			case EKeywordHide:						
       
   841 			case EKeywordFile:
       
   842 			case EKeywordData:
       
   843 			case EKeywordFileCompress:
       
   844 			case EKeywordFileUncompress:
       
   845 		        if (!ProcessDriveFile(keyword))
       
   846 				  return KErrGeneral;
       
   847 		        break;
       
   848 	
       
   849 			default:							
       
   850 		        break;
       
   851 			}
       
   852 		}
       
   853 
       
   854 	if(!ParsePatchDllData())
       
   855 		return KErrGeneral;
       
   856     if (iMissingFiles)   
       
   857 		{
       
   858 		Print(EError, "Source Files Missing.\n");
       
   859 		return KErrGeneral;
       
   860 		}
       
   861 	if (!iNumberOfFiles)
       
   862 		Print(EWarning,"No files specified.\n");
       
   863 	
       
   864 	return KErrNone;
       
   865 	}
       
   866 
       
   867 
       
   868 /**
       
   869 Process and stores the keyword information.
       
   870 
       
   871 @param aKeyword - keyword to update its value to variables.
       
   872 @return - Return the status i.e Success,
       
   873 */
       
   874 TBool CObeyFile::ProcessDriveKeyword(enum EKeyword aKeyword)
       
   875 	{
       
   876 
       
   877 	TBool success = ETrue;
       
   878 	switch (aKeyword)
       
   879 		{
       
   880 		case EKeywordDataImageName:
       
   881 			iReader.CopyWord(1, iDriveFileName);
       
   882 			break;
       
   883 		case EKeywordDataImageFileSystem:
       
   884 			iReader.CopyWord(1, iDriveFileFormat);
       
   885 			break;
       
   886 		case EKeywordDataImageSize:
       
   887 			{
       
   888 			char* bigString = iReader.Word(1);
       
   889 			if(*bigString == '\0')
       
   890 				{
       
   891 				Print(EWarning,"Not a valid Image Size. Default size is considered\n");		
       
   892 				break;
       
   893 				}
       
   894 #ifdef __LINUX__
       
   895 			errno = 0;
       
   896 			iDataSize = strtoll(bigString,NULL,10);
       
   897 			if((iDataSize == LONG_MAX) || (iDataSize == LONG_MIN) ||(errno == ERANGE))
       
   898 				{
       
   899 				Print(EWarning,"Invalid Range. Default size is considered\n");		
       
   900 				}
       
   901 #else
       
   902 			iDataSize = _atoi64(bigString);
       
   903 #endif
       
   904 			}
       
   905 			break;
       
   906 		case EKeywordDataImageVolume:
       
   907 			{				
       
   908 				// Get the volume label provided by using "volume" keyword.
       
   909 				// e.g. vlolume = NO NAME
       
   910 				String volumeLabel = (char*)iReader.GetCurrentObeyStatement();
       
   911 				String volumeLabelKeyword = "volume";
       
   912 
       
   913 				TUint position = volumeLabel.find(volumeLabelKeyword.c_str(),0,volumeLabelKeyword.size());
       
   914 				position += volumeLabelKeyword.size();
       
   915 				if (volumeLabel.find('=',position) != std::string::npos)
       
   916 				{
       
   917 					position=volumeLabel.find('=',position);
       
   918 					++position;
       
   919 				}								
       
   920 
       
   921 				position = volumeLabel.find_first_not_of(' ',position);
       
   922 				if (position != std::string::npos)
       
   923 				{
       
   924 					volumeLabel = volumeLabel.substr(position);
       
   925 
       
   926 					// Remove the new line character from the end
       
   927 					position = volumeLabel.find_first_of("\r\n");
       
   928 					if (position != std::string::npos)
       
   929 						volumeLabel = volumeLabel.substr(0,position);
       
   930 
       
   931 					iConfigurableFatAttributes->iDriveVolumeLabel = volumeLabel.data(); 								
       
   932 				}
       
   933 				else
       
   934 				{
       
   935 					Print(EWarning,"Value for Volume Label is not provided. Default value is considered.\n");
       
   936 				}
       
   937 				break;
       
   938 			}
       
   939 		case EKeywordDataImageSectorSize:
       
   940 			{
       
   941 				char* bigString = iReader.Word(1);
       
   942 				TInt sectorSize = atoi(bigString);
       
   943 				if(sectorSize <= 0)
       
   944 				{
       
   945 					Print(EWarning,"Invalid Sector Size value. Default value is considered.\n");
       
   946 				}
       
   947 				else
       
   948 				{
       
   949 					iConfigurableFatAttributes->iDriveSectorSize = atoi(bigString);
       
   950 				}
       
   951 			}			
       
   952 			break;
       
   953 		case EKeywordDataImageNoOfFats:
       
   954 			{
       
   955 				char* bigString = iReader.Word(1);
       
   956 				TInt noOfFats = atoi(bigString);
       
   957 				if (noOfFats <=0)
       
   958 				{
       
   959 					Print(EWarning,"Invalid No of FATs specified. Default value is considered.\n");
       
   960 				}
       
   961 				else
       
   962 				{
       
   963 					iConfigurableFatAttributes->iDriveNoOfFATs = atoi(bigString);			
       
   964 				}
       
   965 			}			
       
   966 			break;			
       
   967 		default:
       
   968 			// unexpected keyword iReader.Word(0), keep going.
       
   969 			break;
       
   970 		}
       
   971 	return success;
       
   972 	}
       
   973 
       
   974 
       
   975 /**
       
   976 Checks whether obeyfile has supplied enough variables to continue.
       
   977 
       
   978 @return - Return the status 
       
   979 		  ETrue - Supplied valid values,
       
   980 		  EFalse- Not valied values.
       
   981 */
       
   982 TBool CObeyFile::GotKeyDriveVariables()
       
   983    	{
       
   984 
       
   985 	TBool retVal=ETrue;
       
   986 
       
   987 	// Mandatory keywords
       
   988 	if (iDriveFileName==0)                             
       
   989 		{                                                  
       
   990 		Print(EError,"The name of the image file has not been supplied.\n");
       
   991 		Print(EError,"Use the keyword \"dataimagename\".\n");
       
   992 		retVal = EFalse;
       
   993 		}
       
   994 		
       
   995 	// Check for '-'ve entered value.
       
   996 	if(iDataSize <= 0)
       
   997 		{
       
   998 		Print(EWarning,"Image Size should be positive. Default size is Considered.\n");
       
   999 		}
       
  1000 
       
  1001 	// File system format.
       
  1002 	if(iDriveFileFormat==0)
       
  1003 		{
       
  1004 		Print(EError,"The name of the file system not been supplied.\n");
       
  1005 		Print(EError,"Use the keyword \"dataimagefilesystem\".\n");
       
  1006 		retVal = EFalse;
       
  1007 		}
       
  1008 
       
  1009 	// Checking the validity of file system format.
       
  1010 	if(iDriveFileFormat)
       
  1011 		{
       
  1012 		strupr((char *)iDriveFileFormat);
       
  1013 		enum TFileSystem check = (TFileSystem)0;
       
  1014 		if(!(CDriveImage::FormatTranslation(iDriveFileFormat,check)))
       
  1015 			{
       
  1016 			Print(EError,"The name of the file system not supported : %s\n",iDriveFileFormat);
       
  1017 			retVal = EFalse;
       
  1018 			}
       
  1019 		}
       
  1020 	
       
  1021 	if(retVal)
       
  1022 		Print(ELog,"\nCreating Data Drive image : %s\n", iDriveFileName);
       
  1023 
       
  1024   	return retVal;
       
  1025 	}
       
  1026 
       
  1027 /**
       
  1028 Process a parsed line to set up one or more new TRomBuilder entry objects.
       
  1029 
       
  1030 @param  - obey file keyword.
       
  1031 // iWord[0] = the keyword (file,)      
       
  1032 // iWord[1] = the PC pathname
       
  1033 // iWord[2] = the EPOC pathname
       
  1034 // iWord[3] = start of the file attributes
       
  1035 
       
  1036 @return - Return the status 
       
  1037 		  ETrue - Successful generation of tree.
       
  1038 		  EFalse- Fail to generate the tree.
       
  1039 */
       
  1040 TBool CObeyFile::ProcessDriveFile(enum EKeyword aKeyword)               
       
  1041 	{
       
  1042 
       
  1043 	TBool isPeFile = ETrue;
       
  1044 	TBool aFileCompressOption, aFileUncompressOption;
       
  1045 
       
  1046 	TInt epocPathStart=2;
       
  1047 	aFileCompressOption = aFileUncompressOption = EFalse;
       
  1048 	// do some validation of the keyword
       
  1049 	TInt currentLine = iReader.CurrentLine();
       
  1050 
       
  1051 	switch (aKeyword)
       
  1052 		{
       
  1053 		case EKeywordData:
       
  1054 		case EKeywordHide:
       
  1055 			isPeFile = EFalse;
       
  1056 			break;
       
  1057 
       
  1058 		case EKeywordFile:
       
  1059 			break;
       
  1060 
       
  1061 		case EKeywordFileCompress:
       
  1062 			aFileCompressOption = ETrue;
       
  1063 			break;
       
  1064 
       
  1065 		case EKeywordFileUncompress:
       
  1066 			aFileUncompressOption = ETrue;
       
  1067 			break;
       
  1068 
       
  1069 		default:
       
  1070 			return EFalse;
       
  1071 		}
       
  1072 
       
  1073 	if (aKeyword!=EKeywordHide)
       
  1074 		{
       
  1075 		// check the PC file exists
       
  1076 		char* nname = NormaliseFileName(iReader.Word(1));                 
       
  1077 
       
  1078 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)																		  
       
  1079 		ifstream test(nname);
       
  1080 #else //!__MSVCDOTNET__
       
  1081 		ifstream test(nname, ios::nocreate);
       
  1082 #endif //__MSVCDOTNET__
       
  1083 
       
  1084 		if (!test)
       
  1085 			{
       
  1086 			Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
       
  1087 			iMissingFiles++;
       
  1088 			}
       
  1089 
       
  1090 		test.close();
       
  1091 		if(nname)
       
  1092 			free(nname);												
       
  1093 		nname = 0;
       
  1094 		}
       
  1095 	else
       
  1096 		epocPathStart=1;   
       
  1097 
       
  1098 	iNumberOfFiles++;
       
  1099 
       
  1100 	TBool endOfName=EFalse;
       
  1101 	TText *epocStartPtr=IsValidFilePath(iReader.Text(epocPathStart));
       
  1102 	TText *epocEndPtr=epocStartPtr;
       
  1103 
       
  1104 	if (epocStartPtr==NULL)
       
  1105 		{
       
  1106 		Print(EError, "Invalid destination path on line %d\n",currentLine);
       
  1107 		return EFalse;
       
  1108 		}
       
  1109 
       
  1110 	TRomNode* dir=iRootDirectory;
       
  1111 	TRomNode* subDir=0;
       
  1112 	TRomBuilderEntry *file=0;      
       
  1113 
       
  1114 	while (!endOfName)
       
  1115 		{
       
  1116 		endOfName = GetNextBitOfFileName(&epocEndPtr);      
       
  1117 		if (endOfName) // file
       
  1118 			{
       
  1119 			TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
       
  1120 
       
  1121 			if ((aKeyword != EKeywordHide) && alreadyExists) // duplicate file
       
  1122 				{
       
  1123 				Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1124 				return EFalse;
       
  1125 				}
       
  1126 			else if((aKeyword == EKeywordHide) && (alreadyExists))
       
  1127 				{ 
       
  1128 				alreadyExists->iEntry->iHidden = ETrue;
       
  1129 				alreadyExists->iHidden = ETrue;
       
  1130 				return ETrue;
       
  1131 				}
       
  1132 			else if((aKeyword == EKeywordHide) && (!alreadyExists))
       
  1133 				{
       
  1134 				Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1135 				return ETrue;
       
  1136 				}
       
  1137 				
       
  1138 			file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);                   
       
  1139 			file->iExecutable=isPeFile;
       
  1140 			if( aFileCompressOption )
       
  1141 			{
       
  1142 			file->iCompressEnabled = ECompressionCompress;
       
  1143 			}
       
  1144 			else if(aFileUncompressOption )
       
  1145 			{
       
  1146 			file->iCompressEnabled = ECompressionUncompress;
       
  1147 			}
       
  1148 			
       
  1149 			TRomNode* node=new TRomNode(epocStartPtr, file);
       
  1150 			if (node==0)
       
  1151 				return EFalse;
       
  1152 
       
  1153 			TInt r=ParseFileAttributes(node, file, aKeyword);         
       
  1154 			if (r!=KErrNone)
       
  1155 				return EFalse;
       
  1156 
       
  1157 			if(gCompress != ECompressionUnknown)
       
  1158 			{
       
  1159 			node->iFileUpdate = ETrue;
       
  1160 			}
       
  1161 
       
  1162 			if((node->iOverride) || (aFileCompressOption) || (aFileUncompressOption))
       
  1163 			{
       
  1164 			node->iFileUpdate = ETrue;
       
  1165 			}
       
  1166 
       
  1167 			dir->AddFile(node);	// to drive directory structure.
       
  1168 			}		 
       
  1169 		else	
       
  1170 		{
       
  1171 		// directory
       
  1172 		subDir = dir->FindInDirectory(epocStartPtr);      
       
  1173 		if (!subDir) // sub directory does not exist
       
  1174 			{
       
  1175 			if(aKeyword==EKeywordHide)
       
  1176 			{
       
  1177 			Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1178 			return ETrue;
       
  1179 			}
       
  1180 			subDir = dir->NewSubDir(epocStartPtr);
       
  1181 			if (!subDir)
       
  1182 				return EFalse;
       
  1183 			}
       
  1184 			dir=subDir;
       
  1185 
       
  1186 			epocStartPtr = epocEndPtr;
       
  1187 			}  // end of else.
       
  1188 		}
       
  1189 	return ETrue;
       
  1190 	}
       
  1191 
       
  1192 
       
  1193 TInt CObeyFile::SetStackSize(TRomNode *aNode, TText *aStr)
       
  1194 	{
       
  1195 	if (isNumber(aStr)==0)
       
  1196 		return Print(EError, "Number required as argument for keyword 'stack'.\n");
       
  1197 	aNode->SetStackSize( getNumber(aStr) );
       
  1198 	return KErrNone;
       
  1199 	}
       
  1200 
       
  1201 TInt CObeyFile::SetHeapSizeMin(TRomNode *aNode, TText *aStr)
       
  1202 	{
       
  1203 	if (isNumber(aStr)==0)
       
  1204 		return Print(EError, "Number required as argument for keyword 'heapmin'.\n");
       
  1205 	aNode->SetHeapSizeMin( getNumber(aStr) );
       
  1206 	return KErrNone;
       
  1207 	}
       
  1208 
       
  1209 TInt CObeyFile::SetHeapSizeMax(TRomNode *aNode, TText *aStr)
       
  1210 	{
       
  1211 	if (isNumber(aStr)==0)
       
  1212 		return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
       
  1213 	aNode->SetHeapSizeMax( getNumber(aStr) );
       
  1214 	return KErrNone;
       
  1215 	}
       
  1216 
       
  1217 TInt CObeyFile::SetCapability(TRomNode *aNode, TText *aStr)
       
  1218 	{
       
  1219 	if (isNumber(aStr))
       
  1220 		{
       
  1221 		Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
       
  1222 		return KErrNone;
       
  1223 		}
       
  1224 	SCapabilitySet cap;
       
  1225 	TInt r = ParseCapabilitiesArg(cap, (char*)aStr);
       
  1226 	if( KErrNone == r )
       
  1227 		{
       
  1228 		aNode->SetCapability( cap );
       
  1229 		}
       
  1230 	return r;
       
  1231 	}
       
  1232 
       
  1233 TInt CObeyFile::SetPriority(TRomNode *aNode, TText *aStr)
       
  1234 	{
       
  1235 	TProcessPriority priority;
       
  1236 	if (isNumber(aStr))
       
  1237 		{
       
  1238 		priority = (TProcessPriority)getNumber(aStr);
       
  1239 		}
       
  1240 	else
       
  1241 		{
       
  1242 		char *str=(char *)aStr;
       
  1243 		if (stricmp(str, "low")==0)
       
  1244 			priority=EPriorityLow;
       
  1245 		else if (strnicmp(str, "background", 4)==0)
       
  1246 			priority=EPriorityBackground;
       
  1247 		else if (strnicmp(str, "foreground", 4)==0)
       
  1248 			priority=EPriorityForeground;
       
  1249 		else if (stricmp(str, "high")==0)
       
  1250 			priority=EPriorityHigh;
       
  1251 		else if (strnicmp(str, "windowserver",3)==0)
       
  1252 			priority=EPriorityWindowServer;
       
  1253 		else if (strnicmp(str, "fileserver",4)==0)
       
  1254 			priority=EPriorityFileServer;
       
  1255 		else if (strnicmp(str, "realtimeserver",4)==0)
       
  1256 			priority=EPriorityRealTimeServer;
       
  1257 		else if (strnicmp(str, "supervisor",3)==0)
       
  1258 			priority=EPrioritySupervisor;
       
  1259 		else
       
  1260 			return Print(EError, "Unrecognised priority keyword.\n");
       
  1261 		}
       
  1262 	if (priority<EPriorityLow || priority>EPrioritySupervisor)
       
  1263 		return Print(EError, "Priority out of range.\n");
       
  1264 
       
  1265 	aNode->SetPriority( priority );
       
  1266 	return KErrNone;
       
  1267 	}
       
  1268 
       
  1269 TInt CObeyFile::SetUid1(TRomNode *aNode, TText *aStr)
       
  1270 	{
       
  1271 	if (isNumber(aStr)==0)
       
  1272 		return Print(EError, "Number required as argument for keyword 'uid1'.\n");
       
  1273 	aNode->SetUid1( getNumber(aStr) );
       
  1274 	return KErrNone;
       
  1275 	}
       
  1276 TInt CObeyFile::SetUid2(TRomNode *aNode, TText *aStr)
       
  1277 	{
       
  1278 	if (isNumber(aStr)==0)
       
  1279 		return Print(EError, "Number required as argument for keyword 'uid2'.\n");
       
  1280 	aNode->SetUid2( getNumber(aStr) );
       
  1281 	return KErrNone;
       
  1282 	}
       
  1283 TInt CObeyFile::SetUid3(TRomNode *aNode, TText *aStr)
       
  1284 	{
       
  1285 	if (isNumber(aStr)==0)
       
  1286 		return Print(EError, "Number required as argument for keyword 'uid3'.\n");
       
  1287 	aNode->SetUid3( getNumber(aStr) );
       
  1288 	return KErrNone;
       
  1289 	}
       
  1290 
       
  1291 
       
  1292 TInt CObeyFile::ParseFileAttributes(TRomNode *aNode, TRomBuilderEntry* aFile, enum EKeyword aKeyword)
       
  1293 //
       
  1294 // Process any inline keywords
       
  1295 //
       
  1296 	{
       
  1297 	TInt currentLine = iReader.CurrentLine();
       
  1298 	enum EFileAttribute attribute;
       
  1299 	TInt r=KErrNone;
       
  1300 	TInt index=3;
       
  1301 	TText* arg=0;
       
  1302 
       
  1303 	while(r==KErrNone)
       
  1304 		{
       
  1305 		r=iReader.NextAttribute(index,(aFile!=0),attribute,arg);
       
  1306 		if (r!=KErrNone)
       
  1307 			break;
       
  1308 		switch(attribute)
       
  1309 			{
       
  1310 		case EAttributeAtt:
       
  1311 			r=aNode->SetAtt(arg);
       
  1312 			break;
       
  1313 		case EAttributeAttExtra:
       
  1314 			r=aNode->SetAttExtra(arg, aFile, aKeyword);
       
  1315 			break;
       
  1316 		case EAttributeStack:
       
  1317 			r=SetStackSize(aNode, arg);
       
  1318 			break;
       
  1319 		case EAttributeFixed:
       
  1320 			aNode->SetFixed();
       
  1321 			r = KErrNone;
       
  1322 			break;
       
  1323 		case EAttributeUid1:
       
  1324 			r=SetUid1(aNode, arg);
       
  1325 			break;
       
  1326 		case EAttributeUid2:
       
  1327 			r=SetUid2(aNode, arg);
       
  1328 			break;
       
  1329 		case EAttributeUid3:
       
  1330 			r=SetUid3(aNode, arg);
       
  1331 			break;
       
  1332 		case EAttributeHeapMin:
       
  1333 			r=SetHeapSizeMin(aNode, arg);
       
  1334 			break;
       
  1335 		case EAttributeHeapMax:
       
  1336 			r=SetHeapSizeMax(aNode, arg);
       
  1337 			break;
       
  1338 		case EAttributePriority:
       
  1339 			r=SetPriority(aNode, arg);
       
  1340 			break;
       
  1341 		case EAttributeCapability:
       
  1342 			r=SetCapability(aNode, arg);
       
  1343 			break;
       
  1344 		case EAttributeUnpaged:
       
  1345 			aNode->iOverride |= KOverrideCodeUnpaged|KOverrideDataUnpaged;
       
  1346 			aNode->iOverride &= ~(KOverrideCodePaged|KOverrideDataPaged);
       
  1347 			break;
       
  1348 		case EAttributePaged:
       
  1349 			aNode->iOverride |= KOverrideCodePaged|KOverrideDataPaged;
       
  1350 			aNode->iOverride &= ~(KOverrideCodeUnpaged|KOverrideDataUnpaged);
       
  1351 			break;
       
  1352 		case EAttributeUnpagedCode:
       
  1353 			aNode->iOverride |= KOverrideCodeUnpaged;
       
  1354 			aNode->iOverride &= ~KOverrideCodePaged;
       
  1355 			break;
       
  1356 		case EAttributePagedCode:
       
  1357 			aNode->iOverride |= KOverrideCodePaged;
       
  1358 			aNode->iOverride &= ~KOverrideCodeUnpaged;
       
  1359 			break;
       
  1360 		case EAttributeUnpagedData:
       
  1361 			aNode->iOverride |= KOverrideDataUnpaged;
       
  1362 			aNode->iOverride &= ~KOverrideDataPaged;
       
  1363 			break;
       
  1364 		case EAttributePagedData:
       
  1365 			aNode->iOverride |= KOverrideDataPaged;
       
  1366 			aNode->iOverride &= ~KOverrideDataUnpaged;
       
  1367 			break;
       
  1368 
       
  1369 		default:
       
  1370 			return Print(EError, "Unrecognised keyword in file attributes on line %d.\n",currentLine);
       
  1371 			}
       
  1372 		}
       
  1373 
       
  1374 	if (r==KErrEof)
       
  1375 		return KErrNone;
       
  1376 	return r;
       
  1377 	}
       
  1378 
       
  1379 
       
  1380 TBool CObeyFile::ProcessFile(TInt /*aAlign*/, enum EKeyword aKeyword)
       
  1381 //
       
  1382 // Process a parsed line to set up one or more new TRomBuilder entry objects.
       
  1383 // iWord[0] = the keyword (file, primary or secondary)
       
  1384 // iWord[1] = the PC pathname
       
  1385 // iWord[2] = the EPOC pathname
       
  1386 // iWord[3] = start of the file attributes
       
  1387 //
       
  1388 	{
       
  1389 	TBool isPeFile = ETrue;
       
  1390 	TBool aFileCompressOption, aFileUncompressOption;
       
  1391 	TInt epocPathStart=2;
       
  1392 	aFileCompressOption = aFileUncompressOption = EFalse;
       
  1393  	TBool warnFlag = EFalse;
       
  1394  	static const char aStdPath[] = "SYS\\BIN\\";
       
  1395  	static const int sysBinLength = sizeof(aStdPath)-1;
       
  1396 
       
  1397 	// do some validation of the keyword
       
  1398 	TInt currentLine = iReader.CurrentLine();
       
  1399 
       
  1400 	switch (aKeyword)
       
  1401 		{
       
  1402 	case EKeywordData:
       
  1403 	case EKeywordHideV2:
       
  1404 		iNumberOfDataFiles++;
       
  1405 		isPeFile = EFalse;
       
  1406 		break;
       
  1407 
       
  1408 	case EKeywordFile:
       
  1409 		warnFlag = gEnableStdPathWarning;
       
  1410 		break;
       
  1411 	case EKeywordFileCompress:
       
  1412 		aFileCompressOption = ETrue;
       
  1413 		warnFlag = gEnableStdPathWarning;
       
  1414 		break;
       
  1415 	case EKeywordFileUncompress:
       
  1416 		aFileUncompressOption = ETrue;
       
  1417 		warnFlag = gEnableStdPathWarning;
       
  1418 		break;
       
  1419 
       
  1420 	default:
       
  1421 		Print(EError,"Unexpected keyword '%s' on line %d.\n",iReader.Word(0),currentLine);
       
  1422 		return EFalse;
       
  1423 		}
       
  1424 
       
  1425 	if (aKeyword!=EKeywordHideV2)
       
  1426 		{
       
  1427 
       
  1428 		// check the PC file exists
       
  1429 		char* nname = NormaliseFileName(iReader.Word(1));
       
  1430 
       
  1431 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1432 		ifstream test(nname);
       
  1433 #else //!__MSVCDOTNET__
       
  1434 		ifstream test(nname, ios::nocreate);
       
  1435 #endif //__MSVCDOTNET__
       
  1436 
       
  1437 		if (!test)
       
  1438 			{
       
  1439 			Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
       
  1440 			iMissingFiles++;
       
  1441 			}
       
  1442 		test.close();
       
  1443 		free(nname);
       
  1444 		}
       
  1445 	else
       
  1446 		epocPathStart=1;
       
  1447 
       
  1448 	iNumberOfFiles++;
       
  1449 
       
  1450 
       
  1451  	TBool endOfName=EFalse;
       
  1452 	TText *epocStartPtr=IsValidFilePath(iReader.Text(epocPathStart));
       
  1453 	TText *epocEndPtr=epocStartPtr;
       
  1454 	if (epocStartPtr==NULL)
       
  1455 		{
       
  1456 		Print(EError, "Invalid destination path on line %d\n",currentLine);
       
  1457 		return EFalse;
       
  1458 		}
       
  1459  	if(warnFlag)	// Check for the std destination path(for executables) as per platsec.
       
  1460  		{
       
  1461  		if(strnicmp(aStdPath,(const char*)epocStartPtr,sysBinLength) != 0)
       
  1462  			{
       
  1463  			Print(EWarning,"Invalid destination path on line %d. \"%s\" \n",currentLine,epocStartPtr);
       
  1464  			}
       
  1465 		}
       
  1466 	
       
  1467 	TRomNode* dir=iRootDirectory;
       
  1468 	TRomNode* subDir=0;
       
  1469 	TRomBuilderEntry *file=0;
       
  1470 	while (!endOfName)
       
  1471 		{
       
  1472 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1473 		if (endOfName) // file
       
  1474 			{
       
  1475 			TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
       
  1476 			/*
       
  1477 			 * The EKeywordHideV2 keyword is used to indicate that:
       
  1478 			 *	1. if the file exists in the same image and then hidden, mark it hidden
       
  1479 			 *	2. if the file exists in another image, but in this (ROFS) image, it is
       
  1480 			 *		required to hide that file, create a 0 length file entry setting the 'hide'
       
  1481 			 *		flag so that at runtime, file gets hidden in the composite filesystem.
       
  1482 			 */
       
  1483 			if ((aKeyword != EKeywordHideV2) && alreadyExists) // duplicate file
       
  1484 				{
       
  1485 				Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1486 				return EFalse;
       
  1487 				}
       
  1488 
       
  1489 			TBool aHidden = aKeyword==EKeywordHideV2;
       
  1490 			/* The file is only marked hidden and hence the source file name isn't known 
       
  1491 			 * here as hide statement says :
       
  1492 			 *	hide <filename as in ROM>
       
  1493 			 * Therefore, create TRomBuilderEntry with iFileName as 0 for hidden file when
       
  1494 			 * the file doesn't exist in the same ROM image. Otherwise, the src file name
       
  1495 			 * is known because of alreadyExists (which comes from the 'file'/'data' statement).
       
  1496 			 */
       
  1497 			if(aHidden)
       
  1498 				file = new TRomBuilderEntry(0, epocStartPtr);
       
  1499 			else
       
  1500 				file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);
       
  1501 			file->iExecutable=isPeFile;
       
  1502 			file->iHidden= aHidden;
       
  1503 			if( aFileCompressOption )
       
  1504 			{
       
  1505 				file->iCompressEnabled = ECompressionCompress;
       
  1506 			}
       
  1507 			else if(aFileUncompressOption )
       
  1508 			{
       
  1509 				file->iCompressEnabled = ECompressionUncompress;
       
  1510 			}
       
  1511 			TRomNode* node=new TRomNode(epocStartPtr, file);
       
  1512 			if (node==0)
       
  1513 				return EFalse;
       
  1514 			TInt r=ParseFileAttributes(node, file, aKeyword);
       
  1515 			if (r!=KErrNone)
       
  1516 				return EFalse;
       
  1517 
       
  1518 			dir->AddFile(node);	// to ROFS directory structure
       
  1519 			AddFile(file);		// to our list of files
       
  1520 			}		 
       
  1521 		else // directory
       
  1522 			{
       
  1523 			subDir = dir->FindInDirectory(epocStartPtr);
       
  1524 			if (!subDir) // sub directory does not exist
       
  1525 				{
       
  1526 				subDir = dir->NewSubDir(epocStartPtr);
       
  1527 				if (!subDir)
       
  1528 					return EFalse;
       
  1529 				}
       
  1530 			dir=subDir;
       
  1531 			epocStartPtr = epocEndPtr;
       
  1532 			}
       
  1533 		}
       
  1534 	return ETrue;
       
  1535 	}
       
  1536 
       
  1537 
       
  1538 TBool CObeyFile::ProcessRenaming(enum EKeyword aKeyword)
       
  1539 	{
       
  1540 
       
  1541 	// find existing file
       
  1542 	TBool endOfName=EFalse;
       
  1543 	TText *epocStartPtr=IsValidFilePath(iReader.Text(1));
       
  1544 	
       
  1545 	// Store the current name and new name to maintain renamed file map
       
  1546 	String currentName=iReader.Word(1);
       
  1547 	String newName=iReader.Word(2);
       
  1548 
       
  1549 	TText *epocEndPtr=epocStartPtr;
       
  1550 	if (epocStartPtr==NULL)
       
  1551 		{
       
  1552 		Print(EError, "Invalid source path on line %d\n",iReader.CurrentLine());
       
  1553 		return EFalse;
       
  1554 		}
       
  1555 
       
  1556 	char saved_srcname[257];
       
  1557 	strcpy(saved_srcname, iReader.Word(1));
       
  1558 
       
  1559 	TRomNode* dir=iRootDirectory;
       
  1560 	TRomNode* existingFile=0;
       
  1561 	while (!endOfName)
       
  1562 		{
       
  1563 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1564 		if (endOfName) // file
       
  1565 			{
       
  1566 			existingFile=dir->FindInDirectory(epocStartPtr);
       
  1567 			if (existingFile)
       
  1568 				{
       
  1569 				TInt fileCount=0;
       
  1570 				TInt dirCount=0;
       
  1571 				existingFile->CountDirectory(fileCount, dirCount);
       
  1572 				if (dirCount != 0 || fileCount != 0)
       
  1573 					{
       
  1574 					Print(EError, "Keyword %s not applicable to directories - line %d\n",iReader.Word(0),iReader.CurrentLine());
       
  1575 					return EFalse;
       
  1576 					}
       
  1577 				}
       
  1578 			}
       
  1579 		else // directory
       
  1580 			{
       
  1581 			TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
       
  1582 			if (!subDir) // sub directory does not exist
       
  1583 				break;
       
  1584 			dir=subDir;
       
  1585 			epocStartPtr = epocEndPtr;
       
  1586 			}
       
  1587 		}
       
  1588 	if (aKeyword == EKeywordHide)
       
  1589 		{
       
  1590 			/*
       
  1591 			 * The EKeywordHide keyword is used to indicate that if the file exists in 
       
  1592 			 * the primary ROFS image and then hidden in extension ROFS, mark it hidden.
       
  1593 			 */
       
  1594 		if (!existingFile)
       
  1595 			{
       
  1596 			Print(EWarning, "Hiding non-existent file %s on line %d\n", 
       
  1597 				saved_srcname, iReader.CurrentLine());
       
  1598 			// Just a warning, as we've achieved the right overall effect.
       
  1599 			}
       
  1600 		else if (existingFile->iFileStartOffset==(TUint)KFileHidden)
       
  1601 			{
       
  1602 			Print(EWarning, "Hiding already hidden file %s on line %d\n", 
       
  1603 				saved_srcname, iReader.CurrentLine());
       
  1604 			// We will igrore this request, otherwise it will "undelete" it.
       
  1605 			}
       
  1606 		else
       
  1607 			{
       
  1608 			  //hidden files will not be placed to the image
       
  1609 			  existingFile->iHidden = ETrue;
       
  1610 			}
       
  1611 		return ETrue;
       
  1612 		}
       
  1613 
       
  1614 	if (!existingFile)
       
  1615 		{
       
  1616 		Print(EError, "Can't %s non-existent source file %s on line %d\n",
       
  1617 			iReader.Word(0), saved_srcname, iReader.CurrentLine());
       
  1618 		return EFalse;
       
  1619 		}
       
  1620 
       
  1621 	epocStartPtr=IsValidFilePath(iReader.Text(2));
       
  1622 	epocEndPtr=epocStartPtr;
       
  1623 	endOfName=EFalse;
       
  1624 	if (epocStartPtr==NULL)
       
  1625 		{
       
  1626 		Print(EError, "Invalid destination path on line %d\n",iReader.CurrentLine());
       
  1627 		return EFalse;
       
  1628 		}
       
  1629 
       
  1630 	TRomNode* newdir=iRootDirectory;
       
  1631 	while (!endOfName)
       
  1632 		{
       
  1633 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1634 		if (endOfName) // file
       
  1635 			{
       
  1636 			TRomNode* alreadyExists=newdir->FindInDirectory(epocStartPtr);
       
  1637 			if (alreadyExists && !(alreadyExists->iHidden)) // duplicate file
       
  1638 				{
       
  1639 				Print(EError, "Duplicate file for %s on line %d\n",saved_srcname,iReader.CurrentLine());
       
  1640 				return EFalse;
       
  1641 				}
       
  1642 			}
       
  1643 		else // directory
       
  1644 			{
       
  1645 			TRomNode* subDir = newdir->FindInDirectory(epocStartPtr);
       
  1646 			if (!subDir) // sub directory does not exist
       
  1647 				{
       
  1648 				subDir = newdir->NewSubDir(epocStartPtr);
       
  1649 				if (!subDir)
       
  1650 					return EFalse;
       
  1651 				}
       
  1652 			newdir=subDir;
       
  1653 			epocStartPtr = epocEndPtr;
       
  1654 			}
       
  1655 		}
       
  1656 
       
  1657 	if (aKeyword == EKeywordRename)
       
  1658 		{
       
  1659 		// rename => remove existingFile and insert into tree at new place
       
  1660 		// has no effect on the iNextExecutable or iNextNodeForSameFile links
       
  1661 
       
  1662 		TInt r=ParseFileAttributes(existingFile, existingFile->iEntry, aKeyword);
       
  1663 		if (r!=KErrNone)
       
  1664 			return EFalse;
       
  1665 		existingFile->Rename(dir, newdir, epocStartPtr);
       
  1666 		// Store the current and new name of file in the renamed file map.
       
  1667 		iPatchData->AddToRenamedFileMap(currentName, newName);
       
  1668 		return ETrue;
       
  1669 		}
       
  1670 	
       
  1671 	// alias => create new TRomNode entry and insert into tree
       
  1672 
       
  1673 	TRomNode* node = new TRomNode(epocStartPtr, 0);
       
  1674 	if (node == 0)
       
  1675 		{
       
  1676 		Print(EError, "Out of memory\n");
       
  1677 		return EFalse;
       
  1678 		}
       
  1679 	node->Alias(existingFile);
       
  1680 	TInt r=ParseFileAttributes(node, 0, aKeyword);
       
  1681 	if (r!=KErrNone)
       
  1682 		return EFalse;
       
  1683 
       
  1684 	newdir->AddFile(node);	// to ROFS directory structure, though possibly hidden
       
  1685 
       
  1686 	return ETrue;
       
  1687 	}
       
  1688 
       
  1689 TInt ParsePagingPolicy(const char* policy)
       
  1690 	{
       
  1691 	if(stricmp(policy,"NOPAGING")==0)
       
  1692 		return EKernelConfigPagingPolicyNoPaging;
       
  1693 	else if (stricmp(policy,"ALWAYSPAGE")==0)
       
  1694 		return EKernelConfigPagingPolicyAlwaysPage;
       
  1695 	else if(stricmp(policy,"DEFAULTUNPAGED")==0)
       
  1696 		return EKernelConfigPagingPolicyDefaultUnpaged;
       
  1697 	else if(stricmp(policy,"DEFAULTPAGED")==0)
       
  1698 		return EKernelConfigPagingPolicyDefaultPaged;
       
  1699 	return KErrArgument;
       
  1700 	}
       
  1701 
       
  1702 TBool CObeyFile::ProcessKeyword(enum EKeyword aKeyword)
       
  1703 	{
       
  1704 	#ifdef __TOOLS2__
       
  1705 	istringstream val(iReader.Word(1));
       
  1706 	#else
       
  1707 	istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  1708 	#endif
       
  1709 
       
  1710 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1711 	val >> setbase(0);
       
  1712 #endif //__MSVCDOTNET__
       
  1713 
       
  1714 	TBool success = ETrue;
       
  1715 
       
  1716 	switch (aKeyword)
       
  1717 		{
       
  1718 	case EKeywordRofsName:
       
  1719 		iReader.CopyWord(1, iRomFileName);
       
  1720 		break;
       
  1721 	case EKeywordRofsSize:
       
  1722 		val >> iRomSize;
       
  1723 		break;
       
  1724 	case EKeywordVersion:
       
  1725 		val >> iVersion;
       
  1726 		break;
       
  1727 	case EKeywordRofsChecksum:
       
  1728 		val >> iCheckSum;
       
  1729 		break;
       
  1730 	case EKeywordTime:
       
  1731 		iReader.ProcessTime(iTime);
       
  1732 		break;
       
  1733 	case EKeywordPagingOverride:
       
  1734 		{
       
  1735 		if(iPagingOverrideParsed)
       
  1736 			Print(EWarning, "PagingOverride redefined - previous PagingOverride values lost\n");
       
  1737 		if(iCodePagingOverrideParsed)
       
  1738 			Print(EWarning, "PagingOverride defined - previous CodePagingOverride values lost\n");
       
  1739 		if(iDataPagingOverrideParsed)
       
  1740 			Print(EWarning, "PagingOverride defined - previous DataPagingOverride values lost\n");
       
  1741 		iPagingOverrideParsed = true;
       
  1742 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1743 		if(policy<0)
       
  1744 			{
       
  1745 			Print(EError,"Unrecognised option for PAGINGOVERRIDE keyword\n");
       
  1746 			success = false;
       
  1747 			}
       
  1748 		else
       
  1749 			{
       
  1750 			gCodePagingOverride = policy;
       
  1751 			gDataPagingOverride = policy;
       
  1752 			}
       
  1753 		}
       
  1754 		break;
       
  1755 	case EKeywordCodePagingOverride:
       
  1756 		{
       
  1757 		if(iCodePagingOverrideParsed)
       
  1758 			Print(EWarning, "CodePagingOverride redefined - previous CodePagingOverride values lost\n");
       
  1759 		if(iPagingOverrideParsed)
       
  1760 			Print(EWarning, "CodePagingOverride defined - previous PagingOverride values lost\n");
       
  1761 		iCodePagingOverrideParsed = true;
       
  1762 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1763 		if(policy<0)
       
  1764 			{
       
  1765 			Print(EError,"Unrecognised option for CODEPAGINGOVERRIDE keyword\n");
       
  1766 			success = false;
       
  1767 			}
       
  1768 		else
       
  1769 			gCodePagingOverride = policy;
       
  1770 		}
       
  1771 		break;
       
  1772 	case EKeywordDataPagingOverride:
       
  1773 		{
       
  1774 		if(iDataPagingOverrideParsed)
       
  1775 			Print(EWarning, "DataPagingOverride redefined - previous DataPagingOverride values lost\n");
       
  1776 		if(iPagingOverrideParsed)
       
  1777 			{
       
  1778 			Print(EError, "DataPagingOverride defined - previous PagingOverride values lost\n");
       
  1779 			success = false;
       
  1780 			break;
       
  1781 			}
       
  1782 		iDataPagingOverrideParsed = true;
       
  1783 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1784 		if(policy<0)
       
  1785 			{
       
  1786 			Print(EError,"Unrecognised option for DATAPAGINGOVERRIDE keyword\n");
       
  1787 			success = false;
       
  1788 			}
       
  1789 		else
       
  1790 			gDataPagingOverride = policy;
       
  1791 		}
       
  1792 		break;
       
  1793 	case EKeywordRofsAutoSize:
       
  1794 		iAutoSize = ETrue;
       
  1795 		val >> iAutoPageSize;
       
  1796 		break;
       
  1797 	default:
       
  1798 		// unexpected keyword iReader.Word(0)
       
  1799 		break;
       
  1800 		}
       
  1801 
       
  1802 	return success;
       
  1803 	}
       
  1804 
       
  1805 TBool CObeyFile::GotKeyVariables()
       
  1806 //
       
  1807 // Checks that the obeyfile has supplied enough variables to continue
       
  1808 //
       
  1809    	{
       
  1810 
       
  1811 	TBool retVal=ETrue;
       
  1812 
       
  1813 	// Mandatory keywords
       
  1814 
       
  1815 	if (iRomFileName==0)
       
  1816 		{
       
  1817 		Print(EAlways,"The name of the image file has not been supplied.\n");
       
  1818 		Print(EAlways,"Use the keyword \"rofsname\".\n");
       
  1819 		retVal = EFalse;
       
  1820 		}
       
  1821 	if (iRomSize==0)
       
  1822 		{
       
  1823 		Print(EAlways,"The size of the image has not been supplied.\n");
       
  1824 		Print(EAlways,"Use the keyword \"rofssize\".\n");
       
  1825 		retVal = EFalse;
       
  1826 		}
       
  1827 
       
  1828 	// Apply defaults as necessary
       
  1829 	if (iTime==0)
       
  1830 		{
       
  1831 		Print(ELog, "No timestamp specified. Using current time...\n");
       
  1832 		ObeyFileReader::TimeNow(iTime);
       
  1833 		}
       
  1834 
       
  1835 	Print(ELog, "\nCreating Rofs image %s\n", iRomFileName);
       
  1836 	return retVal;
       
  1837 	}
       
  1838 
       
  1839 
       
  1840 TText *CObeyFile::IsValidFilePath(TText *aPath)
       
  1841 //
       
  1842 // Check the path is valid
       
  1843 //
       
  1844 	{
       
  1845 	// skip leading "\"
       
  1846 	if (*aPath=='\\')
       
  1847 		aPath++;
       
  1848 	if (*aPath==0)
       
  1849 		return NULL; // file ends in a backslash
       
  1850 
       
  1851 	TText *p=aPath;
       
  1852 	TInt len=0;
       
  1853 	FOREVER
       
  1854 		{
       
  1855 		if (*p==0)
       
  1856 			return (len ? aPath : NULL);
       
  1857 		if (*p=='\\')
       
  1858 			{
       
  1859 			if (len==0)
       
  1860 				return NULL;
       
  1861 			len=0;
       
  1862 			}
       
  1863 		len++;
       
  1864 		p++;
       
  1865 		}
       
  1866 	}
       
  1867 
       
  1868 TBool CObeyFile::GetNextBitOfFileName(TText **epocEndPtr)
       
  1869 //
       
  1870 // Move the end pointer past the next directory separator, replacing it with 0
       
  1871 //
       
  1872 	{
       
  1873 	while (**epocEndPtr != '\\') // until reach the directory separator
       
  1874 		{
       
  1875 		if (**epocEndPtr==0) // if reach end of string, return TRUE, it's the filename
       
  1876 			return ETrue;
       
  1877 		(*epocEndPtr)++;
       
  1878 		}
       
  1879 	**epocEndPtr=0; // overwrite the directory separator with a 0
       
  1880 	(*epocEndPtr)++; // point past the 0 ready for the next one
       
  1881 	return EFalse;
       
  1882 	}
       
  1883 
       
  1884 
       
  1885 void CObeyFile::AddFile(TRomBuilderEntry* aFile)
       
  1886 	{
       
  1887 	*iNextFilePtrPtr = aFile;
       
  1888 	iNextFilePtrPtr = &(aFile->iNext);
       
  1889 	}
       
  1890 
       
  1891 
       
  1892 
       
  1893 TInt CObeyFile::ProcessExtensionRofs(MRofsImage* aKernelRom)
       
  1894 	{
       
  1895 	//
       
  1896 	// First pass through the obey file to set up key variables
       
  1897 	//
       
  1898 
       
  1899 
       
  1900         iReader.Rewind();
       
  1901 
       
  1902 	enum EKeyword keyword;
       
  1903 
       
  1904 	// Deal with the "extensionrofs" keyword, which should be first
       
  1905 		
       
  1906 	if (iReader.NextLine(1,keyword) != KErrNone)
       
  1907 		return KErrEof;
       
  1908 	if (keyword != EKeywordExtensionRofs)
       
  1909 		return Print(EError, "Unexpected keyword '%s' at start of extension rom - line %d\n",
       
  1910 			iReader.Word(0), iReader.CurrentLine());
       
  1911 	
       
  1912 	iReader.CopyWord(1, iRomFileName);
       
  1913 	Print(ELog, "\n========================================================\n");
       
  1914 	Print(ELog, "Extension ROFS %s starting at line %d\n\n", iRomFileName, iReader.CurrentLine());
       
  1915 
       
  1916 
       
  1917 	iReader.MarkNext();		// so that we rewind to the line after the extensionrom keyword
       
  1918 
       
  1919 	while (iReader.NextLine(1,keyword) != KErrEof)
       
  1920 		{
       
  1921 		if (keyword == EKeywordExtensionRofs)
       
  1922 			break;
       
  1923 			ProcessExtensionKeyword(keyword);
       
  1924 		}
       
  1925 
       
  1926 	if (!GotExtensionVariables(aKernelRom))
       
  1927 		return KErrGeneral;
       
  1928 
       
  1929 	// second pass to process the file specifications in the obey file building
       
  1930 	// up the TRomNode directory structure and the TRomBuilderEntry list
       
  1931 	//
       
  1932 	iReader.Rewind();
       
  1933 
       
  1934 	//
       
  1935 	if (aKernelRom==0)
       
  1936 		return Print(EError, "Option to extend a kernel ROFS image not yet implemented\n");
       
  1937 
       
  1938 
       
  1939 	
       
  1940 	iRootDirectory = new TRomNode((TText*)"");
       
  1941 	
       
  1942 	iLastExecutable = 0;
       
  1943 
       
  1944 	(aKernelRom->RootDirectory())->deleteTheFirstNode();
       
  1945 
       
  1946 
       
  1947 	iRootDirectory = aKernelRom->CopyDirectory(iLastExecutable);
       
  1948 	aKernelRom->SetRootDirectory(iRootDirectory);
       
  1949 
       
  1950 
       
  1951 	TInt align=0;
       
  1952 	while (iReader.NextLine(2,keyword)!=KErrEof)
       
  1953 		{
       
  1954 		if (keyword == EKeywordExtensionRofs)
       
  1955 			break;
       
  1956 
       
  1957 		switch (keyword)
       
  1958 			{
       
  1959 		case EKeywordHide:
       
  1960 		case EKeywordAlias:
       
  1961 		case EKeywordRename:
       
  1962 			if (!ProcessRenaming(keyword))
       
  1963 				return KErrGeneral;
       
  1964 			break;
       
  1965 
       
  1966 		case EKeywordPatchDllData:
       
  1967 		{	
       
  1968 			// Collect patchdata statements to process at the end
       
  1969 			StringVector patchDataTokens;
       
  1970 			SplitPatchDataStatement(patchDataTokens); 
       
  1971 			iPatchData->AddPatchDataStatement(patchDataTokens);									
       
  1972 			break;
       
  1973 		}
       
  1974 		default:
       
  1975 			if (!ProcessFile(align, keyword))
       
  1976 				return KErrGeneral;
       
  1977 			align=0;
       
  1978 			break;
       
  1979 			}
       
  1980 		}
       
  1981 
       
  1982 	if(!ParsePatchDllData() )
       
  1983 		return KErrGeneral;
       
  1984 	
       
  1985 	iReader.Mark();			// ready for processing the next extension rom(s)
       
  1986 
       
  1987 	if (iMissingFiles!=0)
       
  1988 		return KErrGeneral;
       
  1989 	if (iNumberOfFiles==0)
       
  1990 		{
       
  1991 		Print(EError, "No files specified.\n");
       
  1992 		return KErrGeneral;
       
  1993 		}
       
  1994 	return KErrNone;
       
  1995 	}
       
  1996 
       
  1997 
       
  1998 
       
  1999 
       
  2000 void CObeyFile::ProcessExtensionKeyword(enum EKeyword aKeyword)
       
  2001 	{
       
  2002 	#ifdef __TOOLS2__
       
  2003 	istringstream val(iReader.Word(1));
       
  2004 	#else
       
  2005 	istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  2006 	#endif
       
  2007 
       
  2008 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  2009 	val >> setbase(0);
       
  2010 #endif //__MSVCDOTNET__
       
  2011 
       
  2012 	switch (aKeyword)
       
  2013 		{
       
  2014 	case EKeywordCoreRofsName:
       
  2015  		iReader.CopyWord(1, iKernelRofsName);
       
  2016 		return;
       
  2017 	case EKeywordRofsSize:
       
  2018 		val >> iRomSize;
       
  2019 		return;
       
  2020 	case EKeywordVersion:
       
  2021 		val >> iVersion;
       
  2022 		return;
       
  2023 	case EKeywordRomChecksum:
       
  2024 		val >> iCheckSum;
       
  2025 		return;
       
  2026 	case EKeywordTime:
       
  2027 		iReader.ProcessTime(iTime);
       
  2028 		return;
       
  2029 	case EKeywordRofsAutoSize:
       
  2030 		iAutoSize = ETrue;
       
  2031 		val >> iAutoPageSize;
       
  2032 		return;
       
  2033 	default:
       
  2034 		Print(EError,"Keyword '%s' not valid in extension ROFS - line %d\n", iReader.Word(0), iReader.CurrentLine());
       
  2035 		break;
       
  2036 		}
       
  2037 	return;
       
  2038 	}
       
  2039 
       
  2040 TBool CObeyFile::GotExtensionVariables(MRofsImage* aRom)
       
  2041 //
       
  2042 // Checks that the obeyfile has supplied enough variables to continue
       
  2043 //
       
  2044    	{
       
  2045 
       
  2046 	TBool retVal=ETrue;
       
  2047   	TText* kernelRofsName = iKernelRofsName;
       
  2048 
       
  2049 	// Mandatory keywords
       
  2050 
       
  2051 	if (iRomSize==0)
       
  2052 		{
       
  2053 		Print(EAlways,"The size of the extension ROFS has not been supplied.\n");
       
  2054 		Print(EAlways,"Use the keyword \"rofssize\".\n");
       
  2055 		retVal = EFalse;
       
  2056 		}
       
  2057 
       
  2058 	// keywords we need if we don't already have a ROFS image to work from
       
  2059 
       
  2060 	if (aRom==0)
       
  2061 		{
       
  2062   		if (iKernelRofsName==0)
       
  2063 			{
       
  2064 			Print(EAlways,"The name of the core ROFS has not been supplied.\n");
       
  2065 			Print(EAlways,"Use the keyword \"rofsname\".\n");
       
  2066 			retVal = EFalse;
       
  2067 			}
       
  2068 		}
       
  2069 	else
       
  2070 		{
       
  2071 		if (iKernelRofsName != 0)
       
  2072 			{
       
  2073 			Print(EWarning,"Keyword \"rofsname\" ignored.\n");
       
  2074 			}
       
  2075 		kernelRofsName = aRom->RomFileName();
       
  2076 		}
       
  2077 
       
  2078 	// validation
       
  2079 
       
  2080 	// Apply defaults as necessary
       
  2081 	if (iTime==0)
       
  2082 		{
       
  2083 		Print(ELog, "No timestamp specified. Using current time...\n");
       
  2084 		ObeyFileReader::TimeNow(iTime);
       
  2085 		}
       
  2086 
       
  2087 	// fix up "*" in rofsname
       
  2088 	TText newname[256];
       
  2089 	TText* p=newname;
       
  2090 	TText* q=iRomFileName;
       
  2091 	TText c;
       
  2092 
       
  2093 	while ((c=*q++)!='\0')
       
  2094 		{
       
  2095 		if (c!='*')
       
  2096 			{
       
  2097 			*p++=c;
       
  2098 			continue;
       
  2099 			}
       
  2100 		TText *r=kernelRofsName;
       
  2101 		while ((c=*r++)!='\0')
       
  2102 			*p++=c;
       
  2103 		}
       
  2104 	*p = '\0';
       
  2105 	free(iRomFileName);
       
  2106   	iRomFileName = (TText*)strdup((char*)newname);
       
  2107 
       
  2108 	Print(ELog, "\nCreating ROFS image %s\n", iRomFileName);
       
  2109 
       
  2110 	return retVal;
       
  2111 	}
       
  2112 
       
  2113 // Fuction to split patchdata statement 
       
  2114 void CObeyFile::SplitPatchDataStatement(StringVector& aPatchDataTokens)
       
  2115 {
       
  2116 	// Get the value of symbol size, address/ordinal and new value 
       
  2117 	// to be patched from the patchdata statement.
       
  2118 	// Syntax of patchdata statements is as follows:
       
  2119 	// 1)	patchdata dll_name  ordinal OrdinalNumber size_in_bytes   new_value 
       
  2120 	// 2)   patchdata dll_name  addr    Address       size_in_bytes   new_value
       
  2121 	for(TInt count=1; count<=5; count++)
       
  2122 	{
       
  2123 		aPatchDataTokens.push_back(iReader.Word(count));
       
  2124 	}
       
  2125 
       
  2126 	// Store the the value of current line which will be used
       
  2127 	// when displaying error messages.
       
  2128 	OutputStringStream outStrStream;
       
  2129 	outStrStream<<iReader.CurrentLine();
       
  2130     aPatchDataTokens.push_back(outStrStream.str());
       
  2131 }
       
  2132 
       
  2133 TBool CObeyFile::ParsePatchDllData()
       
  2134 {
       
  2135 	// Get the list of patchdata statements
       
  2136 	VectorOfStringVector patchDataStatements=iPatchData->GetPatchDataStatements();
       
  2137 	// Get the list of renamed file map
       
  2138 	MapOfString RenamedFileMap=iPatchData->GetRenamedFileMap();
       
  2139 
       
  2140 	for(TUint count=0; count<patchDataStatements.size(); count++)
       
  2141 	{
       
  2142 		StringVector strVector = patchDataStatements.at(count);
       
  2143 		String filename=strVector.at(0);
       
  2144 		String lineNoStr = strVector.at(5);
       
  2145 		TUint lineNo=getNumber(((TText*)lineNoStr.c_str()));
       
  2146 		TRomNode* existingFile = NULL;
       
  2147 		
       
  2148 		do
       
  2149 		{
       
  2150 			TRomNode* dir=iRootDirectory;			
       
  2151 			TBool endOfName=EFalse;
       
  2152 
       
  2153 			TText *epocStartPtr=IsValidFilePath((TText*)filename.c_str());
       
  2154 			if (epocStartPtr==NULL)
       
  2155 			{
       
  2156 				Print(EError, "Invalid source path on line %d\n",lineNo);
       
  2157 				return EFalse;
       
  2158 			}
       
  2159 			epocStartPtr = (TText*)NormaliseFileName((const char*)epocStartPtr);
       
  2160 			TText *epocEndPtr=epocStartPtr;
       
  2161 
       
  2162 			while (!endOfName)
       
  2163 			{
       
  2164 				endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  2165 				if (endOfName) // file
       
  2166 				{
       
  2167 					existingFile=dir->FindInDirectory(epocStartPtr);
       
  2168 					if (existingFile)
       
  2169 					{
       
  2170 						TInt fileCount=0;
       
  2171 						TInt dirCount=0;
       
  2172 						existingFile->CountDirectory(fileCount, dirCount);
       
  2173 						if (dirCount != 0 || fileCount != 0)
       
  2174 						{
       
  2175 							Print(EError, "Keyword %s not applicable to directories - line %d\n","patchdata",lineNo);
       
  2176 							return EFalse;
       
  2177 						}
       
  2178 					}
       
  2179 				}
       
  2180 				else // directory
       
  2181 				{
       
  2182 					TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
       
  2183 					if (!subDir) // sub directory does not exist
       
  2184 						break;
       
  2185 					dir=subDir;
       
  2186 					epocStartPtr = epocEndPtr;
       
  2187 				}
       
  2188 			}
       
  2189 
       
  2190 			if(!existingFile)
       
  2191 			{
       
  2192 				// If the E32Image file to be patched is not included then check if the
       
  2193 				// file was renamed.
       
  2194 				MapOfStringIterator RenamedFileMapIterator;
       
  2195 				if ((RenamedFileMapIterator=RenamedFileMap.find(filename)) != RenamedFileMap.end())
       
  2196 					filename = (*RenamedFileMapIterator).second; 				
       
  2197 				else
       
  2198 				{
       
  2199 					Print(EError, "File %s not found - line %d\n", filename.c_str(), lineNo);
       
  2200 					return EFalse;
       
  2201 				}
       
  2202 			}
       
  2203 		}while(!existingFile);
       
  2204 
       
  2205 		TUint32 aSize, aOrdinal, aNewValue, aOffset;
       
  2206 		TLinAddr aDataAddr;
       
  2207 
       
  2208 		aOrdinal = (TUint32)-1;
       
  2209 		aDataAddr = (TUint32)-1;
       
  2210 		aOffset = 0;
       
  2211 
       
  2212 		String symbolSize=strVector.at(3);
       
  2213 		aSize = getNumber((TText*)symbolSize.c_str());
       
  2214 		String aValue=strVector.at(4);
       
  2215 		aNewValue = getNumber((TText*)aValue.c_str());		
       
  2216 
       
  2217 		DllDataEntry *dataEntry = new DllDataEntry(aSize, aNewValue);
       
  2218 
       
  2219 		// Set the address of the data or the ordinal number specified in OBY statement.
       
  2220 		String keyword=strVector.at(1);
       
  2221 		String keywordValue=strVector.at(2);
       
  2222 		
       
  2223 		/* Check for +OFFSET at the end of the ordinal number or address */
       
  2224 		TUint plus = keywordValue.find("+",0);
       
  2225 		if (plus != std::string::npos)
       
  2226 		{
       
  2227 			/* Get the offset that we found after the + sign */
       
  2228 			String offset = keywordValue.substr(plus+1);
       
  2229 			aOffset = getNumber((TText*)offset.c_str());
       
  2230 
       
  2231 			keywordValue.resize(plus);		
       
  2232 		}
       
  2233 		if(stricmp (keyword.c_str(), "addr") == 0)
       
  2234 			aDataAddr = getNumber((TText*)keywordValue.c_str());
       
  2235 		
       
  2236 		else 
       
  2237 			 aOrdinal = getNumber((TText*)keywordValue.c_str());
       
  2238 		
       
  2239 		dataEntry->iDataAddress = aDataAddr;
       
  2240 		dataEntry->iOrdinal = aOrdinal;
       
  2241 		dataEntry->iOffset = aOffset;
       
  2242 
       
  2243 		existingFile->SetDllData();
       
  2244 
       
  2245 		DllDataEntry *aDllDataEntry= existingFile->iEntry->GetFirstDllDataEntry();
       
  2246 		if (aDllDataEntry==NULL)
       
  2247 		{
       
  2248 			// Set the first node of the patchdata linked list
       
  2249 			aDllDataEntry=dataEntry;
       
  2250 			existingFile->iEntry->SetFirstDllDataEntry(aDllDataEntry);
       
  2251 		}
       
  2252 		else
       
  2253 		{
       
  2254 			// Goto the last node
       
  2255 			while((aDllDataEntry->NextDllDataEntry()) != NULL)
       
  2256 			{
       
  2257 				aDllDataEntry = aDllDataEntry->NextDllDataEntry();
       
  2258 			}
       
  2259 			
       
  2260 			// Add the new node at the end of linked list
       
  2261 			aDllDataEntry->AddDllDataEntry(dataEntry);			
       
  2262 		}
       
  2263 	}
       
  2264 	return ETrue;
       
  2265 }
       
  2266 
       
  2267 
       
  2268 
       
  2269 
       
  2270 
       
  2271 
       
  2272 
       
  2273 
       
  2274