imgtools/romtools/rofsbuild/r_build.cpp
changeset 590 360bd6b35136
parent 0 044383f39525
child 626 ac03b93ca9c4
--- a/imgtools/romtools/rofsbuild/r_build.cpp	Wed Jun 16 16:51:40 2010 +0300
+++ b/imgtools/romtools/rofsbuild/r_build.cpp	Wed Jun 23 16:56:47 2010 +0800
@@ -1,1415 +1,1313 @@
-/*
-* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: 
-* @internalComponent * @released
-*
-*/
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32rom.h>
-#include <u32std.h>
-#include <e32uid.h>
-#include <f32file.h>
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-	#include <iomanip>
-	#include <strstream>
-#else //!__MSVCDOTNET__
-	#include <iomanip.h>
-#endif //__MSVCDOTNET__
-
-#ifdef _L
-#undef _L
-#endif
-
-#include "h_utl.h"
-#include "r_obey.h"
-#include "rofs.h"
-#include "e32image.h"
-#include "patchdataprocessor.h"
-
-extern TUint checkSum(const void* aPtr);
-
-extern ECompression gCompress;
-extern TUint gCompressionMethod;
-extern TInt  gCodePagingOverride;
-extern TInt  gDataPagingOverride;
-extern TInt  gLogLevel;
-TBool gDriveImage=EFalse;	// for drive image support.
-
-
-TInt TRomNode::Count=0;
-TRomNode* TRomNode::TheFirstNode = NULL;
-TRomNode* TRomNode::TheLastNode = NULL;
-
-// introduced for data drive files' attribute
-TUint8 TRomNode::sDefaultInitialAttr = (TUint8)KEntryAttReadOnly;
-
-struct SortableEntry
-	{
-	TRofsEntry* iEntry;
-	TBool iIsDir;
-	TUint16 iOffset;
-	};
-
-int compare(const void* l, const void* r)
-	{
-	const SortableEntry* left  = (const SortableEntry*)l;
-	const SortableEntry* right = (const SortableEntry*)r;
-	if (left->iIsDir)
-		{
-		if (!right->iIsDir)
-			return -1;	// dir < file
-		}
-	else
-		{
-		if (right->iIsDir)
-			return +1;	// file > dir
-		}
-
-	// both the same type of entry, sort by name
-	// must first convert to an 8 bit string
-	// array and NULL terminate it.
-	char temp1[500];
-	char temp2[500];
-
-
-TInt i=0;
-	for (i = 0; i < left->iEntry->iNameLength; i++)
-		{
-		temp1[i]=(char) left->iEntry->iName[i];
-		}
-	temp1[i]=0;
-
-	for (i = 0; i < right->iEntry->iNameLength; i++)
-		{
-		temp2[i]=(char) right->iEntry->iName[i];
-		}
-	temp2[i]=0;
-
-	return stricmp((const char*)&temp1[0], (const char*)&temp2[0]);
-	}
-
-TRomNode::TRomNode(TText* aName, TRomBuilderEntry* aEntry)
-//
-// Constructor
-//
-	:
-	iNextNode(NULL),
-	iParent(NULL), iSibling(0), iChild(0), iNextNodeForSameFile(0), 
-	iTotalDirectoryBlockSize(0),
-	iTotalFileBlockSize(0),
-	iImagePosition(0),
-	iFileBlockPosition(0),
-	iAtt(sDefaultInitialAttr),
-	iAttExtra(0xFF),
-	iHidden(EFalse),
-	iEntry(aEntry),
-	iFileStartOffset(0), 
-	iSize(0), 
-	iOverride(0),
-	iFileUpdate(EFalse),
-    iAlias(false)
-	{
-	iName = (TText*)NormaliseFileName((const char*)aName);
-	iIdentifier=TRomNode::Count++;
-
-	// Add this node to the flat linked list
-	if( !TheFirstNode )
-		{
-		TheFirstNode = this;
-		}
-	else
-		{
-		TheLastNode->iNextNode = this;
-		}
-	TheLastNode = this;
-
-	if (iEntry)
-		{
-		iEntry->SetRomNode(this);
-		}
-	else
-		{
-		iAtt = (TUint8)KEntryAttDir;
-		}
-	}
-
-TRomNode::~TRomNode()
-	{
-	if (iEntry && !iAlias)
-        {
-		delete iEntry;
-        }
-    iEntry = 0;
-	if(iName)
-		free(iName);
-    iName = 0;
-	}
-
-TRomNode *TRomNode::FindInDirectory(TText *aName)
-//
-// Check if the TRomNode for aName exists in aDir, and if so, return it.
-//
-	{
-
-	TRomNode *entry=iChild; // first subdirectory or file
-	while (entry)
-		{
-		if ((stricmp((const char *)aName, (const char *)entry->iName))==0) 
-			return entry;
-		else
-			entry=entry->iSibling;
-		}
-	return 0;
-	}
-
-
-
-TInt indend = 0;
-
-void indendStructure(TInt i)
-       {
-	while(i > 0)
-	   {
-	     cout << "    ";
-	     i--;
-	   }
-       };  
-
-// displays the directory structure
-void TRomNode::DisplayStructure(ostream* aOut)
-	{
-	  indendStructure(indend);
-      *aOut  << iName << "\n";
-	  if (iChild)
-	    {
-	      indend++; 
-	      iChild->DisplayStructure(aOut);
-	      indend--;
-	    }
-	  if (iSibling)
-	    iSibling->DisplayStructure(aOut);
-	}
-
-
-void TRomNode::deleteTheFirstNode()
-{
-
-	TheFirstNode = NULL;
-}
-
-
-void TRomNode::InitializeCount()
-{
-	Count = 0;
-}
-void TRomNode::displayFlatList()
-{
-	TRomNode* current =	TheFirstNode;
-	TInt i = 0;
-	while(current)
-	{
-		i++;
-		cout <<  "\n" << i <<": " << current->iName << endl;
-		current = current->NextNode();
-	}
-
-	}
-
-
-
-void TRomNode::AddFile(TRomNode* aChild)
-	{
-	if (iEntry)
-		{
-		Print(EError, "Adding subdirectory to a file!!!\n");
-		return;
-		}
-	Add(aChild);
-	}
-
-TRomNode* TRomNode::NewSubDir(TText *aName)
-	{
-	if (iEntry)
-		{
-		Print(EError, "Adding subdirectory to a file!!!\n");
-		return 0;
-		}
-
-	TRomNode* node = new TRomNode(aName );
-	if (node==0)
-		{
-		Print(EError, "TRomNode::NewNode: Out of memory\n");
-		return 0;
-		}
-	node->iParent = this;
-	Add(node);
-	return node;
-	}
-
-void TRomNode::Add(TRomNode* aChild)
-	{
-	if (iChild) // this node is a non-empty directory
-		{
-		TRomNode* dir = iChild; // find where to link in the new node
-		while (dir->iSibling)
-			dir = dir->iSibling;
-		dir->iSibling = aChild;
-		}
-	else
-		iChild = aChild; // else just set it up as the child of the dir
-	aChild->iSibling = 0;
-	aChild->iParent = this;
-	}
-
-TInt TRomNode::SetAttExtra(TText *anAttWord, TRomBuilderEntry* aFile, enum EKeyword aKeyword)
-//
-// Set the file extra attribute byte from the letters passed
-// Note: The iAttExtra bits are inverted. '0' represent enabled
-//
-	{
-	iAttExtra=0xFF;
-	if (anAttWord==0 || anAttWord[0]=='\0')
-		return Print(EError, "Missing argument for keyword 'exattrib'.\n");
-	for (TText *letter=anAttWord;*letter!=0;letter++)
-		{
-		switch (*letter)
-			{
-		case 'u':
-			iAttExtra |= (KEntryAttUnique >> 23);	// '1' represents disabled in iAttExtra
-			break;
-		case 'U':
-			iAttExtra &= ~(KEntryAttUnique >> 23);	// '0' represent enabled in iAttExtra
-			break;
-		default:
-			return Print(EError, "Unrecognised exattrib - '%c'.\n", *letter);
-			break;
-			}
-		}
-
-	if((~iAttExtra & (KEntryAttUnique >> 23))!=0)	// If the unique file attribute is set
-		{
-		if(aKeyword==EKeywordFile || aKeyword==EKeywordData)	// If the Keyword is File or Data
-			{
-				if(strlen(aFile->iFileName) > (KMaxFileName-KRofsMangleNameLength)) // check whether we have enough space to add the mangle tage
-					return Print(EError, "Lengthy filename with unique attribute to name mangle.\n");
-			}
-		else	// for all other keywords
-			return Print(EError, "exattrib field not allowed for entries except data and file.\n");
-		}
-	return KErrNone;
-	}
-
-
-TInt TRomNode::SetAtt(TText *anAttWord)
-//
-// Set the file attribute byte from the letters passed
-//
-	{
-	iAtt=0;
-	if (anAttWord==0 || anAttWord[0]=='\0')
-		return Print(EError, "Missing argument for keyword 'attrib'.\n");
-	for (TText *letter=anAttWord;*letter!=0;letter++)
-		{
-		switch (*letter)
-			{
-		case 'R':
-		case 'w':
-			iAtt |= KEntryAttReadOnly;
-			break;
-		case 'r':
-		case 'W':
-			iAtt &= ~KEntryAttReadOnly;
-			break;
-		case 'H':
-			iAtt |= KEntryAttHidden;
-			break;
-		case 'h':
-			iAtt &= ~KEntryAttHidden;
-			break;
-		case 'S':
-			iAtt |= KEntryAttSystem;
-			break;
-		case 's':
-			iAtt &= ~KEntryAttSystem;
-			break;
-		default:
-			return Print(EError, "Unrecognised attrib - '%c'.\n", *letter);
-			break;
-			}
-		}
-	return KErrNone;
-	}
-
-
-
-TInt TRomNode::CalculateEntrySize() const
-	// Calculates the amount of ROM space required to hold
-	// this entry. The return is the actual size of the TRofsEntry
-	// structure, not rounded up
-	{
-	TInt requiredSizeBytes = KRofsEntryHeaderSize +	NameLengthUnicode();
-	return requiredSizeBytes;
-	}
-
-TInt TRomNode::CalculateDirectoryEntrySize( TInt& aDirectoryBlockSize,
-										    TInt& aFileBlockSize )
-	// Calculates the total size of the TRofsDir structure required
-	// for this directory and the size of the files block. Traverses all the
-	// children adding their entry sizes. The result is not rounded up.
-	//
-	// On return aDirectoryBlockSize is the number of bytes required for the
-	//	main directory structure. aFileBlockSize is the number of bytes
-	//	required to hold the list of files.
-	//
-	// Returns KErrNone on success
-	{
-
-	TInt offsetBytes=0;
-	TInt padBytes=0;
-	if( 0 == iTotalDirectoryBlockSize )
-		{
-		// need to calculate by walking children	
-		if( !iChild )
-			{
-			return Print(EError, "TRomNode structure corrupt\n");
-			}
-
-		TInt dirBlockSize = KRofsDirHeaderSize;
-		TInt fileBlockSize = 0;
-		TInt fileCount=0;
-		TInt dirCount=0;
-
-		TRomNode* node = iChild;
-		while (node)
-			{
-			TInt entrySize = node->CalculateEntrySize();
-			if( node->IsDirectory() )
-				{
-				dirBlockSize += (4 - dirBlockSize) & 3;	// pad to next word boundary
-				dirBlockSize += entrySize;
-				dirCount++;
-				}
-			else
-				{
-				fileBlockSize += (4 - fileBlockSize) & 3;	// pad to next word boundary
-				fileBlockSize += entrySize;
-				fileCount++;
-				}
-			node = node->iSibling;
-			}
-		
-		offsetBytes = ((fileCount + dirCount) * 2) + 4; //the +4 are the two offset counts,
-		padBytes = offsetBytes % 4;
-
-		iTotalDirectoryBlockSize = dirBlockSize;
-		iTotalFileBlockSize = fileBlockSize;
-		}
-
-	aDirectoryBlockSize = iTotalDirectoryBlockSize + offsetBytes + padBytes;
-	aFileBlockSize = iTotalFileBlockSize;
-	return KErrNone;
-	}
-
-/**
-Place the files and it's attributes (incase of executables)
-Called for both rofs and datadrive creation.
- 
-@param aDest   - Destination buffer.
-@param aOffset - offset value, used for rofs only.
-@param aMaxSize- Maximum size required for rofs.
-  
-@return - Returns the number of bytes placed or a -ve error code.
-*/ 
-TInt TRomNode::PlaceFile( TUint8* &aDest, TUint aOffset, TUint aMaxSize, CBytePair *aBPE )
-	//
-	// Place the file into the ROM image, making any necessary conversions
-	// along the way.
-	//
-	// Returns the number of bytes placed or a -ve error code.
-	{
-
-	TInt size=0;
-	
-	// file hasn't been placed for drive image. 
-	if(gDriveImage)
-	{
-		size = iEntry->PlaceFile(aDest,aMaxSize,aBPE);
-		iSize = size;
-	}
-	else
-	{
-		if (iEntry->iHidden)
-			iFileStartOffset = KFileHidden;
-		else
-		{
-                    if (iEntry->iFileOffset==0)
-                    {
-                        // file hasn't been placed
-                        size = iEntry->PlaceFile( aDest, aMaxSize, aBPE );
-                        if (size>=0)
-                            iEntry->iFileOffset = aOffset;
-                    }
-                    else {
-                        iFileStartOffset = (TInt)iEntry;
-                    }
-		}
-	}
-
-	// Deal with any override attributes
-	// (omit paging overrides as these are dealt with in TRomBuilderEntry::PlaceFile
-	//  and may also be legitimately specified for non-executable files in ROM)
-	if( iOverride&~(KOverrideCodeUnpaged|KOverrideCodePaged|KOverrideDataUnpaged|KOverrideDataPaged) )
-		{
-		E32ImageHeaderV* hdr = (E32ImageHeaderV*)aDest;
-
-		TUint hdrfmt = hdr->HeaderFormat();
-		if (hdrfmt != KImageHdrFmt_V)
-			{
-			Print(EError,"%s: Can't load old format binary\n", iEntry->iFileName);
-			return KErrNotSupported;
-			}
-		
-		// First need to check that it's a real image header
-		if( (TUint)size > sizeof(E32ImageHeader) )
-			{
-			if( ((TInt)hdr->iSignature == 0x434f5045u) && ((TInt)hdr->iUid1 == KExecutableImageUidValue || (TInt)hdr->iUid1 == KDynamicLibraryUidValue) )
-				{
-				// Should check the CRC as well here...
-				// Something for later
-
-				// Ok, it looks like an image header
-				if( iOverride & KOverrideStack )
-					{
-					hdr->iStackSize = iStackSize;
-					}
-				if( iOverride & KOverrideHeapMin )
-					{
-					hdr->iHeapSizeMin = iHeapSizeMin;
-					}
-				if( iOverride & KOverrideHeapMax )
-					{
-					hdr->iHeapSizeMax = iHeapSizeMax;
-					}
-				if( iOverride & KOverrideFixed )
-					{
-					if( hdr->iFlags & KImageDll )
-						{
-						Print(EError,"%s: Can't used FIXED keyword on a DLL\n", iEntry->iFileName);
-						return KErrNotSupported;
-						}
-					hdr->iFlags |= KImageFixedAddressExe;
-					}
-				if( iOverride & (KOverrideUid1|KOverrideUid2|KOverrideUid3))
-					{
-					if (iOverride & KOverrideUid1)
-						{
-						hdr->iUid1 = iUid1;
-						}
-					if (iOverride & KOverrideUid2)
-						{
-						hdr->iUid2 = iUid2;
-						}
-					if (iOverride & KOverrideUid3)
-						{
-						hdr->iUid3 = iUid3;
-						}
-					// Need to re-checksum the UIDs
-					TUidType ut(TUidType(TUid::Uid(hdr->iUid1), TUid::Uid(hdr->iUid2), TUid::Uid(hdr->iUid3)));
-					hdr->iUidChecksum =  (checkSum(((TUint8*)&ut)+1)<<16)|checkSum(&ut);
-					}
-				if( iOverride & KOverridePriority )
-					{
-					hdr->iProcessPriority = (TUint16)iPriority;
-					}
-				if( iOverride & KOverrideCapability )
-					{
-					hdr->iS.iCaps = iCapability;
-					}
-
-				// Need to re-CRC the header
-				hdr->iHeaderCrc = KImageCrcInitialiser;
-				TUint32 crc = 0;
-				TInt hdrsz = hdr->TotalSize();
-				HMem::Crc32(crc, hdr, hdrsz);
-				hdr->iHeaderCrc = crc;
-				}
-			}
-		}
-
-	return size;
-	}
-
-TInt TRomNode::CountFileAndDir(TInt& aFileCount, TInt& aDirCount)
-	{
-	//
-	// Count the number of file and directory entries for this node
-	//
-	TRomNode* node = iChild;
-
-	aFileCount=0;
-	aDirCount=0;
-	while( node )
-		{
-		if( node->IsFile() )
-			{
-			aFileCount++;
-			}
-		else
-			{
-			aDirCount++;
-			}
-
-		node = node->iSibling;
-		}
-	return KErrNone;
-	}
-
-TInt TRomNode::Place( TUint8* aDestBase )
-	//
-	// Writes this directory entry out to the image.
-	// The image starts at aDestBase.
-	// The position in the image must already have been set with SetImagePosition()
-	// and SetFileBlockPosition().
-	// Returns KErrNone on success
-	//
-	{
-	TUint8* dirBlockBase = aDestBase + iImagePosition;
-	TUint8* fileBlockBase = aDestBase + iFileBlockPosition;
-
-	TRofsDir* pDir = (TRofsDir*)dirBlockBase;
-	pDir->iFirstEntryOffset = KRofsDirFirstEntryOffset;
-	pDir->iFileBlockAddress = iFileBlockPosition;
-	pDir->iFileBlockSize = iTotalFileBlockSize;
-	pDir->iStructSize = (TUint16)iTotalDirectoryBlockSize;
-
-	TRofsEntry* pDirEntry = &(pDir->iSubDir);
-	TRofsEntry* pFileEntry = (TRofsEntry*)fileBlockBase;
-
-	TInt dirCount;
-	TInt fileCount;
-	TInt index = 0;
-	CountFileAndDir(fileCount, dirCount);
-
-	SortableEntry* array = new SortableEntry[fileCount + dirCount];
-	TRomNode* node = iChild;
-
-	while( node )
-		{
-		TRofsEntry* entry;
-
-		if( node->IsFile() )
-			{
-			entry = pFileEntry;
-
-			//Offset in 32bit words from start of file block
-			array[index].iOffset = (TUint16) ((((TUint8*) entry) - fileBlockBase) >> 2);
-			array[index].iIsDir = EFalse;
-			}
-		else
-			{
-			entry = pDirEntry;
-
-			//Offset in 32bit words from start of directory block
-			array[index].iOffset = (TUint16) ((((TUint8*) entry) - dirBlockBase) >> 2);
-			array[index].iIsDir = ETrue;
-			}
-		array[index].iEntry = entry;
-		index++;
-
-		entry->iNameOffset = KRofsEntryNameOffset;
-		entry->iAtt = node->iAtt;
-		entry->iAttExtra = node->iAttExtra;
-
-		TInt entryLen = KRofsEntryHeaderSize;
-		entryLen += node->NameCpy( (char*)&entry->iName, entry->iNameLength );
-		entryLen += (4 - entryLen) & 3;	// round up to nearest word
-		entry->iStructSize = (TUint16)entryLen;
-
-
-		if( node->IsFile() )
-			{
-			// node is a file, entry points to the file
-			// write an entry out into the file block
-			pFileEntry->iFileAddress = node->iFileStartOffset;
-			node->iAtt &= ~KEntryAttDir;
-			pFileEntry->iFileSize = node->iEntry->RealFileSize();
-			memcpy(&pFileEntry->iUids[0], &node->iEntry->iUids[0], sizeof(pFileEntry->iUids));
-			pFileEntry = (TRofsEntry*)( (TUint8*)pFileEntry + entryLen );
-			}
-		else
-			{
-			// node is a subdirectory, entry points to directory
-			pDirEntry->iFileAddress = node->iImagePosition;
-			node->iAtt |= KEntryAttDir;
-			
-			// the size is just the size of the directory block
-			pDirEntry->iFileSize = node->iTotalDirectoryBlockSize;
-			pDirEntry = (TRofsEntry*)( (TUint8*)pDirEntry + entryLen );
-			}
-
-		node = node->iSibling;
-		}
-
-	qsort(array,fileCount + dirCount,sizeof(SortableEntry),&compare);
-
-	//Now copy the contents of sorted array to the image
-	TUint16* currentPtr = (TUint16*) (dirBlockBase + iTotalDirectoryBlockSize);
-
-	*currentPtr=(TUint16)dirCount;
-	currentPtr++;
-	*currentPtr=(TUint16)fileCount;
-	currentPtr++;
-
-	for (index = 0; index < (fileCount + dirCount); index++)
-		{
-		*currentPtr = array[index].iOffset;
-		currentPtr++;
-		}
-	delete[] array;
-	return KErrNone;
-	}
-
-
-
-void TRomNode::Remove(TRomNode* aChild)
-	{
-	if (iChild==0)
-		{
-		Print(EError, "Removing file from a file!!!\n");
-		return;
-		}
-	if (iChild==aChild) // first child in this directory
-		{
-		iChild = aChild->iSibling;
-		aChild->iSibling = 0;
-		if(iChild==0)
-			{
-				iParent->Remove(this);
-				TRomNode * current = TheFirstNode;
-				TRomNode * prev = current;
-				while(current != this)
-					{
-						prev = current;
-						current = current->NextNode();
-					}
-				prev->SetNextNode(current->NextNode());
-				delete this;
-			}
-		return;
-		}
-	TRomNode* prev = iChild;
-	while (prev->iSibling && prev->iSibling != aChild)
-		prev = prev->iSibling;
-	if (prev==0)
-		{
-		Print(EError, "Attempting to remove file not in this directory!!!\n");
-		return;
-		}
-	prev->iSibling = aChild->iSibling;
-	aChild->iSibling = 0;
-	}
-
-void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount)
-	{
-	TRomNode *current=iChild;
-	while(current)
-		{
-		if (current->iChild)
-			aDirCount++;
-		else
- 			aFileCount++;
-	current=current->iSibling;
-		}
-	}
-
- void TRomNode::Destroy()
-//
-// Follow the TRomNode tree, destroying it
-//
-	{
-
- 	TRomNode *current = this; // root has no siblings
-	while (current)
-		{
-		if (current->iChild)
-			current->iChild->Destroy();
-		TRomNode* prev=current;
-		current=current->iSibling;
-		delete prev;
-        prev = 0;
-		}
- 	}
-
-
-
-
-TInt TRomNode::NameCpy(char* aDest, TUint8& aUnicodeLength )
-//
-// Safely copy a file name in the rom entry
-// Returns the number of bytes used. Write the length in unicode characters
-// into aUnicodeLength.
-//
-	{
-
-	if ((aDest==NULL) || (iName==NULL))
-		return 0;
-	const unsigned char* pSourceByte = (const unsigned char*)iName;
-	unsigned char* pTargetByte=(unsigned char*)aDest;
-	for (;;)
-		{
-		const TUint sourceByte=*pSourceByte;
-		if (sourceByte==0)
-			{
-			break;
-			}
-		if ((sourceByte&0x80)==0)
-			{
-			*pTargetByte=(unsigned char)sourceByte;
-			++pTargetByte;
-			*pTargetByte=0;
-			++pTargetByte;
-			++pSourceByte;
-			}
-		else if ((sourceByte&0xe0)==0xc0)
-			{
-			++pSourceByte;
-			const TUint secondSourceByte=*pSourceByte;
-			if ((secondSourceByte&0xc0)!=0x80)
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(671);
-				}
-			*pTargetByte=(unsigned char)((secondSourceByte&0x3f)|((sourceByte&0x03)<<6));
-			++pTargetByte;
-			*pTargetByte=(unsigned char)((sourceByte>>2)&0x07);
-			++pTargetByte;
-			++pSourceByte;
-			}
-		else if ((sourceByte&0xf0)==0xe0)
-			{
-			++pSourceByte;
-			const TUint secondSourceByte=*pSourceByte;
-			if ((secondSourceByte&0xc0)!=0x80)
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(672);
-				}
-			++pSourceByte;
-			const TUint thirdSourceByte=*pSourceByte;
-			if ((thirdSourceByte&0xc0)!=0x80)
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(673);
-				}
-			*pTargetByte=(unsigned char)((thirdSourceByte&0x3f)|((secondSourceByte&0x03)<<6));
-			++pTargetByte;
-			*pTargetByte=(unsigned char)(((secondSourceByte>>2)&0x0f)|((sourceByte&0x0f)<<4));
-			++pTargetByte;
-			++pSourceByte;
-			}
-		else
-			{
-			Print(EError, "Bad UTF-8 '%s'", iName);
-			exit(674);
-			}
-		}
-	const TInt numberOfBytesInTarget=(pTargetByte-(unsigned char*)aDest); // this number excludes the trailing null-terminator
-	if (numberOfBytesInTarget%2!=0)
-		{
-		Print(EError, "Internal error");
-		exit(675);
-		}
-	aUnicodeLength = (TUint8)(numberOfBytesInTarget/2); // returns the length of aDest (in UTF-16 characters for Unicode, not bytes)
-	return numberOfBytesInTarget;
-	}
-
-
-TInt TRomNode::NameLengthUnicode() const
-//
-// Find the unicode lenght of the name
-//
-	{
-
-	if (iName==NULL)
-		return 0;
-
-	const unsigned char* pSourceByte = (const unsigned char*)iName;
-	TInt len = 0;
-	for (;;)
-		{
-		const TUint sourceByte=*pSourceByte;
-		if (sourceByte==0)
-			{
-			break;
-			}
-		if ((sourceByte&0x80)==0)
-			{
-			len += 2;
-			++pSourceByte;
-			}
-		else if ((sourceByte&0xe0)==0xc0)
-			{
-			++pSourceByte;
-			const TUint secondSourceByte=*pSourceByte;
-			if ((secondSourceByte&0xc0)!=0x80)
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(671);
-				}
-			len += 2;
-			++pSourceByte;
-			}
-		else if ((sourceByte&0xf0)==0xe0)
-			{
-			++pSourceByte;
-			const TUint secondSourceByte=*pSourceByte;
-			if ((secondSourceByte&0xc0)!=0x80)
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(672);
-				}
-			++pSourceByte;
-			const TUint thirdSourceByte=*pSourceByte;
-			if ((thirdSourceByte&0xc0)!=0x80)
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(673);
-				}
-			len += 2;
-			++pSourceByte;
-			}
-		else
-			{
-			Print(EError, "Bad UTF-8 '%s'", iName);
-			exit(674);
-			}
-		}
-	return len;
-	}
-
-
-void TRomNode::AddNodeForSameFile(TRomNode* aPreviousNode, TRomBuilderEntry* aFile)
-	{
-	// sanity checking
-	if (iNextNodeForSameFile != 0 || iEntry != aFile || (aPreviousNode && aPreviousNode->iEntry != iEntry))
-		{
-		Print(EError, "Adding Node for same file: TRomNode structure corrupted\n");
-		exit(666);
-		}
-	iNextNodeForSameFile = aPreviousNode;
-	}
-
-
-
-
-
-//**************************************
-// TRomBuilderEntry
-//**************************************
-
-
-
-TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,TText *aName)
-//
-// Constructor
-//
-:iFirstDllDataEntry(0),	iName(0),iFileName(0),iNext(0), iNextInArea(0),
-iExecutable(EFalse), iFileOffset(EFalse), iCompressEnabled(0),
-iHidden(0), iRomNode(0), iRealFileSize(0)		 
-{
-	if (aFileName)
-   		iFileName = NormaliseFileName(aFileName);
-	if (aName)
-		iName = (TText*)NormaliseFileName((const char*)aName);
-	memset(iUids,0 ,sizeof(TCheckedUid));
-}
-	
-TRomBuilderEntry::~TRomBuilderEntry()
-//
-// Destructor
-//
-	{
-	if(iFileName)
-	{
-	free(iFileName);
-	}
-	iFileName = 0;
-	if(iName)
-	{
-	free(iName);
-	}
-	}
-
-void TRomBuilderEntry::SetRomNode(TRomNode* aNode)
-	{
-	aNode->AddNodeForSameFile(iRomNode, this);
-	iRomNode = aNode;
-	}
-
-
-TInt isNumber(TText *aString)
-	{
-	if (aString==NULL)
-		return 0;
-	if (strlen((char *)aString)==0)
-		return 0;
-	return isdigit(aString[0]);
-	}
-
-TInt getNumber(TText *aStr)
-	{
-	TUint a;
-	#ifdef __TOOLS2__
-	istringstream val((char *)aStr);
-	#else
-	istrstream val((char *)aStr,strlen((char *)aStr));
-	#endif
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-	val >> setbase(0);
-#endif //__MSVCDOTNET__
-
-	val >> a;
-	return a;
-	}
-
-
-TInt TRomBuilderEntry::PlaceFile( TUint8* &aDest,TUint aMaxSize, CBytePair *aBPE )
-	//
-	// Place the file in ROM. Since we don't support compression yet all
-	// we have to do is read the file into memory
-	// compress it, if it isn't already compressed.
-	//
-	// Returns the number of bytes used, or -ve error code
-	{
-	TUint compression = 0;
-	TBool executable = iExecutable;
-	Print(ELog,"Reading file %s to image\n", iFileName );
-	TUint32 size=HFile::GetLength((TText*)iFileName);
-	if (size==0)
-		Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",iFileName);
-        if (aDest == NULL) {
-            aMaxSize = size*2;
-            aMaxSize = (aMaxSize>0) ? aMaxSize : 2;
-            aDest = new TUint8[aMaxSize];
-        }
-
-	if (executable)
-		{
-		// indicate if the image will overflow without compression
-	TBool overflow;
-			if(size>aMaxSize)
-			overflow = ETrue;
-		else
-			overflow = EFalse;
-
-		// try to compress this executable
-		E32ImageFile f(aBPE);
-		TInt r = f.Open(iFileName);
-		// is it really a valid E32ImageFile?
-		if (r != KErrNone)
-			{
-			Print(EWarning, "File '%s' is not a valid executable.  Placing file as data.\n", iFileName);
-			executable = EFalse;
-			}
-		else
-			{
-
-			if(iRomNode->iOverride & KOverrideDllData)
-			{
-				DllDataEntry *aDllEntry = iRomNode->iEntry->GetFirstDllDataEntry();
-				TLinAddr* aExportTbl;
-				void *aLocation;
-				TUint aDataAddr;
-				char *aCodeSeg, *aDataSeg;
-
-				aExportTbl = (TLinAddr*)((char*)f.iData + f.iOrigHdr->iExportDirOffset);
-
-				// const data symbol may belong in the Code section. If the address lies within the Code or data section limits, 
-				// get the corresponding location and update it.While considering the Data section limits
-				// don't include the Bss section, as it doesn't exist as yet in the image.
-				while( aDllEntry ){
-					if(aDllEntry->iOrdinal != (TUint32)-1){
-						if(aDllEntry->iOrdinal < 1 || aDllEntry->iOrdinal > (TUint)f.iOrigHdr->iExportDirCount){
-							Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", aDllEntry->iOrdinal, iRomNode->iName);
-							aDllEntry = aDllEntry->NextDllDataEntry();
-							continue;
-						}
-					
-				//	Get the address of the data field via the export table.
-					aDataAddr = (TInt32)(aExportTbl[aDllEntry->iOrdinal - 1] + aDllEntry->iOffset);
-					if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){
-						aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset);
-						aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase );
-						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
-					}
-					else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){
-						aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset);
-						aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase );
-						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
-					}
-					else
-					{
-						Print(EWarning, "Patchdata failed as address pointed by ordinal %d of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName);
-					}
-					}
-					else if(aDllEntry->iDataAddress != (TLinAddr)-1){
-						aDataAddr = aDllEntry->iDataAddress + aDllEntry->iOffset;
-					if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){
-						aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset);
-						aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase );
-						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
-					}
-					else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){
-						aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset);
-						aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase );
-						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
-					}
-					else
-					{
-						Print(EWarning, "Patchdata failed as address 0x%x of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName);
-					}
-					}
-					aDllEntry = aDllEntry->NextDllDataEntry();
-					}
-			}
-
-			compression = f.iHdr->CompressionType();
-			Print(ELog,"Original file:'%s' is compressed by method:%08x\n", iFileName, compression);
-
-
-			TUint32 oldFileComp;
-			TUint32 newFileComp;
-
-			if(compression)
-			{
-				// The E32 image in release directory is compressed
-				oldFileComp = compression;
-			}
-			else
-			{
-				// The E32 image in release directory is uncompressed
-				oldFileComp = 0;
-			}
-
-			if( iCompressEnabled != ECompressionUnknown)
-			{
-				// The new state would be as stated in obey file, i.e. 
-				// filecompress or fileuncompress
-				newFileComp = gCompressionMethod;
-			}
-			else if (gCompress != ECompressionUnknown)
-			{
-				// The new state would be as stated set globally
-				newFileComp = gCompressionMethod;
-			}
-			else
-			{
-				// When not known if compression is to be applied or not,
-				// set it same as that of the E32 image in release directory
-				newFileComp = oldFileComp;
-			}
-
-			if(!gDriveImage)
-			{
-				// overide paging flags...
-				E32ImageHeaderV* h=f.iHdr;
-				if (iRomNode->iOverride & KOverrideCodePaged)
-					{
-					h->iFlags &= ~KImageCodeUnpaged;
-					h->iFlags |= KImageCodePaged;
-					}
-				if (iRomNode->iOverride & KOverrideCodeUnpaged)
-					{
-					h->iFlags |= KImageCodeUnpaged;
-					h->iFlags &= ~KImageCodePaged;
-					}
-				if (iRomNode->iOverride & KOverrideDataPaged)
-					{
-					h->iFlags &= ~KImageDataUnpaged;
-					h->iFlags |= KImageDataPaged;
-					}
-				if (iRomNode->iOverride & KOverrideDataUnpaged)
-					{
-					h->iFlags |= KImageDataUnpaged;
-					h->iFlags &= ~KImageDataPaged;
-					}
-
-				// apply global paging override...
-				switch(gCodePagingOverride)
-					{
-				case EKernelConfigPagingPolicyNoPaging:
-					h->iFlags |= KImageCodeUnpaged;
-					h->iFlags &= ~KImageCodePaged;
-					break;
-				case EKernelConfigPagingPolicyAlwaysPage:
-					h->iFlags |= KImageCodePaged;
-					h->iFlags &= ~KImageCodeUnpaged;
-					break;
-				case EKernelConfigPagingPolicyDefaultUnpaged:
-					if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
-						h->iFlags |= KImageCodeUnpaged;
-					break;
-				case EKernelConfigPagingPolicyDefaultPaged:
-					if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
-						h->iFlags |= KImageCodePaged;
-					break;
-					}
-				switch(gDataPagingOverride)
-					{
-				case EKernelConfigPagingPolicyNoPaging:
-					h->iFlags |= KImageDataUnpaged;
-					h->iFlags &= ~KImageDataPaged;
-					break;
-				case EKernelConfigPagingPolicyAlwaysPage:
-					h->iFlags |= KImageDataPaged;
-					h->iFlags &= ~KImageDataUnpaged;
-					break;
-				case EKernelConfigPagingPolicyDefaultUnpaged:
-					if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
-						h->iFlags |= KImageDataUnpaged;
-					break;
-				case EKernelConfigPagingPolicyDefaultPaged:
-					if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
-						h->iFlags |= KImageDataPaged;
-					break;
-					}
-				f.UpdateHeaderCrc();
-
-				// make sure paged code has correct compression type...
-				if(h->iFlags&KImageCodePaged)
-					{
-					if(newFileComp!=0)
-						newFileComp = KUidCompressionBytePair;
-					}
-			}
-
-			if ( oldFileComp != newFileComp )
-				{
-				
-				if( newFileComp == 0)
-					{
-					Print(ELog,"Decompressing executable '%s'\n", iFileName);
-					f.iHdr->iCompressionType = 0;
-					}
-				else
-					{
-					Print(ELog,"Compressing executable '%s' with method:%08x\n", iFileName, newFileComp);
-					f.iHdr->iCompressionType = newFileComp;
-					}
-				f.UpdateHeaderCrc();
-				if (overflow)
-					{
-					char * buffer = new char [size];
-					// need to check if the compressed file will fit in the image
-   					#if defined(__LINUX__)
- 					ostrstream os((char*)aDest, aMaxSize, (ios::openmode)(ios::out+ios::binary));
-					#elif defined(__TOOLS2__) && defined (_STLP_THREADS)
-  					ostrstream os((char*)buffer, size,(ios::out+ios::binary));
-  					#elif defined( __TOOLS2__)
-   					ostrstream os((char*)buffer, size,(ios::out+ios::binary));
-					#else
-					ostrstream os( (char*)buffer, size, (ios::out+ios::binary));
-					#endif
-					os << f;
-					TUint compressedSize = os.pcount();
-					if (compressedSize <= aMaxSize)
-						overflow = EFalse;	
-					delete[] buffer;
-					}
-				}
-			if (overflow)
-				{
-				Print(EError, "Can't fit '%s' in image\n", iFileName);
-				Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize);
-				exit(667);
-				}
-  			#if defined(__TOOLS2__) && defined (_STLP_THREADS)
-  			ostrstream os((char*)aDest, aMaxSize,(ios::out+ios::binary));
-  			#elif __TOOLS2__
-			ostrstream os((char*)aDest, aMaxSize, (std::_Ios_Openmode)(ios::out+ios::binary));
-			#else
-			ostrstream os((char*)aDest, aMaxSize, (ios::out+ios::binary));
-			#endif
-			os << f;
-			size = os.pcount();
-			compression = f.iHdr->CompressionType();
-			memcpy(&iUids[0], aDest, sizeof(iUids));
-			}
-		}
-	if (!executable)
-		{
-		if ( size > aMaxSize )
-			{
-			Print(EError, "Can't fit '%s' in image\n", iFileName);
-			Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize);
-			exit(667);
-			}
-		size = HFile::Read((TText*)iFileName, (TAny *)aDest);
-                TUint32 Uidslen = (size > sizeof(iUids)) ? sizeof(iUids) : size;
-                memcpy(&iUids[0], aDest, Uidslen);
-		}
-
-	if (compression)
-		Print(ELog,"Compressed executable File '%s' size: %08x, mode:%08x\n", iFileName, size, compression);
-	else if (iExecutable)
-		Print(ELog,"Executable File '%s' size: %08x\n", iFileName, size);
-	else
-		Print(ELog,"File '%s' size: %08x\n", iFileName, size);
-	iRealFileSize = size;	// required later when directory is written
-	
-	return size;
-	}
-
-
-TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable)
-	{
-
-	if (iHidden && iChild==0)
-		{
-		// Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure)
-		if (iSibling)
-			return iSibling->CopyDirectory(aLastExecutable);
-		else
-			return 0;
-		}
-
-	TRomNode* copy = new TRomNode(iName);
-	if(aLastExecutable==0)
-		aLastExecutable = copy;		// this must be the root of the structure
-	// recursively copy the sub-structures
-	if (iChild)
-		copy->iChild = iChild->CopyDirectory(aLastExecutable);
-	if (iSibling)
-		copy->iSibling = iSibling->CopyDirectory(aLastExecutable);
-	copy->Clone(this);
-	return copy;
-	}
-
-
-
-
-void TRomNode::Clone(TRomNode* aOriginal)
-	{
-	iAtt = aOriginal->iAtt;
-	iAttExtra = aOriginal->iAttExtra;
-	iEntry = aOriginal->iEntry;
-	iHidden = aOriginal->iHidden;
-	iFileStartOffset = aOriginal->iFileStartOffset;
-	iSize = aOriginal->iSize;
-	iParent = aOriginal->iParent;
-    iAlias = aOriginal->iAlias;
-	}
-
-
-void TRomNode::Alias(TRomNode* aNode)
-	{
-	  // sanity checking
-	if (aNode->iEntry == 0) 
-	{
-		Print(EError, "Aliasing: TRomNode structure corrupted\n");
-		exit(666);
-	}
-	Clone(aNode);
-	iEntry = aNode->iEntry;
-	if (iEntry)
-		{
-		iEntry->SetRomNode(this);
-		}
-    iAlias = true;
-	}
-
-
-void TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, TText* aNewName)
-	{
-	aOldParent->Remove(this);
-	aNewParent->Add(this);
-	delete [] iName;
-	iName = new TText[strlen((const char *)aNewName)+1];
-	strcpy ((char *)iName, (const char *)aNewName);
-	}
-
-TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const
-	{
-	TInt l = 0;
-	// aIgnoreHiddenAttrib is used to find the complete file name length as 
-	// in ROM of a hidden file.
-	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
-		l = iParent->FullNameLength() + 1;
-	l += strlen((const char*)iName);
-	return l;
-	}
-
-TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const
-	{
-	TInt l = 0;
-	TInt nl = strlen((const char*)iName);
-	// aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file.
-	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
-		l = iParent->GetFullName(aBuf);
-	char* b = aBuf + l;
-	if (l)
-		*b++ = '\\', ++l;
-	memcpy(b, iName, nl);
-	b += nl;
-	*b = 0;
-	l += nl;
-	return l;
-	}
-
-// Fuction to return first node in the patchdata linked list
-DllDataEntry *TRomBuilderEntry::GetFirstDllDataEntry() const
-{
-	if (iFirstDllDataEntry)
-	{
-		return iFirstDllDataEntry;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-// Fuction to set first node in the patchdata linked list
-void TRomBuilderEntry::SetFirstDllDataEntry(DllDataEntry *aDllDataEntry)
-{
-	iFirstDllDataEntry = aDllDataEntry;	
-}
-void TRomBuilderEntry::DisplaySize(TPrintType aWhere)
-{
-	TBool aIgnoreHiddenAttrib = ETrue;
-	TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib);
-	char *aBuf = new char[aLen+1];
-	if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
-		{
-		iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib);
-		if(iFileName)
-			Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, RealFileSize(), (iRomNode->iHidden || iHidden)?"hidden":"", aBuf);
-		else
-			Print(aWhere, "%s\t%s\n", (iRomNode->iHidden || iHidden)?"hidden":"", aBuf);
-		}
-	else
-		{
-		if(iFileName)
-			Print(aWhere, "%s\t%d\n", iFileName, RealFileSize());
-		}
-
-}
+/*
+* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+* @internalComponent * @released
+*
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <e32std.h>
+#include <e32std_private.h>
+#include <e32rom.h>
+#include <u32std.h>
+#include <e32uid.h>
+#include <f32file.h>
+#include <malloc.h>
+#include <map>
+#include <queue> 
+#include <iomanip>
+#include <strstream>
+#include "utf16string.h"
+#ifdef _L
+#undef _L
+#endif
+#ifdef __LINUX__
+#define _alloca alloca
+#endif
+
+#include "h_utl.h"
+#include "r_obey.h"
+#include "rofs.h"
+#include "e32image.h"
+#include "patchdataprocessor.h"
+
+#include <filesystem.hpp>
+#include <thread/thread.hpp>
+#include <thread/mutex.hpp>
+#include <thread/condition_variable.hpp>
+
+#include "cache/cacheexception.hpp"
+#include "cache/cacheentry.hpp"
+#include "cache/cache.hpp"
+#include "cache/cachegenerator.hpp"
+#include "cache/cachevalidator.hpp"
+#include "cache/cacheablelist.hpp"
+#include "cache/cachemanager.hpp"
+
+extern TUint checkSum(const void* aPtr);
+
+extern ECompression gCompress;
+extern TUint gCompressionMethod;
+extern TInt  gCodePagingOverride;
+extern TInt  gDataPagingOverride;
+extern TInt  gLogLevel;
+extern bool gCache;
+TBool gDriveImage=EFalse;	// for drive image support.
+
+
+TInt TRomNode::Count=0;
+TRomNode* TRomNode::TheFirstNode = NULL;
+TRomNode* TRomNode::TheLastNode = NULL;
+
+// introduced for data drive files' attribute
+TUint8 TRomNode::sDefaultInitialAttr = (TUint8)KEntryAttReadOnly;
+
+struct SortableEntry
+	{
+	TRofsEntry* iEntry;
+	TBool iIsDir;
+	TUint16 iOffset;
+	};
+
+int compare(const void* l, const void* r)
+	{
+	const SortableEntry* left  = (const SortableEntry*)l;
+	const SortableEntry* right = (const SortableEntry*)r;
+	if (left->iIsDir)
+		{
+		if (!right->iIsDir)
+			return -1;	// dir < file
+		}
+	else
+		{
+		if (right->iIsDir)
+			return +1;	// file > dir
+		}
+
+	// both the same type of entry, sort by name
+	// must first convert to an 8 bit string
+	// array and NULL terminate it.
+	char temp1[500];
+	char temp2[500];
+
+
+TInt i=0;
+	for (i = 0; i < left->iEntry->iNameLength; i++)
+		{
+		temp1[i]=(char) left->iEntry->iName[i];
+		}
+	temp1[i]=0;
+
+	for (i = 0; i < right->iEntry->iNameLength; i++)
+		{
+		temp2[i]=(char) right->iEntry->iName[i];
+		}
+	temp2[i]=0;
+
+	return stricmp((const char*)&temp1[0], (const char*)&temp2[0]);
+	}
+
+TRomNode::TRomNode(const char* aName, TRomBuilderEntry* aEntry)
+//
+// Constructor
+//
+	:
+	iNextNode(NULL),
+	iParent(NULL), iSibling(0), iChild(0), iNextNodeForSameFile(0),
+	iTotalDirectoryBlockSize(0),
+	iTotalFileBlockSize(0),
+	iImagePosition(0),
+	iFileBlockPosition(0),
+	iAtt(sDefaultInitialAttr),
+	iAttExtra(0xFF),
+	iHidden(EFalse),
+	iEntry(aEntry),
+	iFileStartOffset(0),
+	iSize(0),
+	iOverride(0),
+	iFileUpdate(EFalse),
+    iAlias(false)
+	{
+	iName = NormaliseFileName(aName);
+	iIdentifier=TRomNode::Count++;
+
+	// Add this node to the flat linked list
+	if( !TheFirstNode )
+		{
+		TheFirstNode = this;
+		}
+	else
+		{
+		TheLastNode->iNextNode = this;
+		}
+	TheLastNode = this;
+
+	if (iEntry)
+		{
+		iEntry->SetRomNode(this);
+		}
+	else
+		{
+		iAtt = (TUint8)KEntryAttDir;
+		}
+	}
+
+TRomNode::~TRomNode() {
+	if (iEntry && !iAlias)
+		delete iEntry; 
+	if(iName)
+		delete []iName ;
+}
+//
+// Check if the TRomNode for aName exists in aDir, and if so, return it.
+//
+TRomNode *TRomNode::FindInDirectory(const char *aName) const{
+	TRomNode *entry=iChild; // first subdirectory or file
+	while (entry) {
+		if ((stricmp(aName, entry->iName)) == 0)
+			return entry;
+		else
+			entry=entry->iSibling;
+	}
+	return 0;
+}
+
+
+
+TInt indend = 0;
+
+void indendStructure(TInt i)
+       {
+	while(i > 0)
+	   {
+	     cout << "    ";
+	     i--;
+	   }
+       };
+
+// displays the directory structure
+void TRomNode::DisplayStructure(ostream* aOut)
+	{
+	  indendStructure(indend);
+      *aOut  << iName << "\n";
+	  if (iChild)
+	    {
+	      indend++;
+	      iChild->DisplayStructure(aOut);
+	      indend--;
+	    }
+	  if (iSibling)
+	    iSibling->DisplayStructure(aOut);
+	}
+
+
+void TRomNode::deleteTheFirstNode()
+{
+
+	TheFirstNode = NULL;
+}
+
+
+void TRomNode::InitializeCount()
+{
+	Count = 0;
+}
+void TRomNode::displayFlatList()
+{
+	TRomNode* current =	TheFirstNode;
+	TInt i = 0;
+	while(current)
+	{
+		i++;
+		cout <<  "\n" << i <<": " << current->iName << endl;
+		current = current->NextNode();
+	}
+
+	}
+
+
+
+void TRomNode::AddFile(TRomNode* aChild)
+	{
+	if (iEntry)
+		{
+		Print(EError, "Adding subdirectory to a file!!!\n");
+		return;
+		}
+	Add(aChild);
+	}
+
+TRomNode* TRomNode::NewSubDir(const char *aName) {
+	if (iEntry) {
+		Print(EError, "Adding subdirectory to a file!!!\n");
+		return 0;
+	}
+
+	TRomNode* node = new TRomNode(aName);
+	if (node==0){
+		Print(EError, "TRomNode::NewNode: Out of memory\n");
+		return 0;
+	}
+	node->iParent = this;
+	Add(node);
+	return node;
+	}
+
+void TRomNode::Add(TRomNode* aChild) {
+	if (iChild){ // this node is a non-empty directory
+		
+		TRomNode* dir = iChild; // find where to link in the new node
+		while (dir->iSibling)
+			dir = dir->iSibling;
+		dir->iSibling = aChild;
+	}
+	else
+		iChild = aChild; // else just set it up as the child of the dir
+	aChild->iSibling = 0;
+	aChild->iParent = this;
+	}
+//
+// Set the file extra attribute byte from the letters passed
+// Note: The iAttExtra bits are inverted. '0' represent enabled
+//
+TInt TRomNode::SetAttExtra(char *anAttWord, TRomBuilderEntry* aFile, enum EKeyword aKeyword){
+	iAttExtra=0xFF;
+	if (anAttWord==0 || anAttWord[0]=='\0')
+		return Print(EError, "Missing argument for keyword 'exattrib'.\n");
+	for (char *letter=anAttWord;*letter!=0;letter++)
+		{
+		switch (*letter)
+			{
+		case 'u':
+			iAttExtra |= (KEntryAttUnique >> 23);	// '1' represents disabled in iAttExtra
+			break;
+		case 'U':
+			iAttExtra &= ~(KEntryAttUnique >> 23);	// '0' represent enabled in iAttExtra
+			break;
+		default:
+			return Print(EError, "Unrecognised exattrib - '%c'.\n", *letter);
+			break;
+			}
+		}
+
+	if((~iAttExtra & (KEntryAttUnique >> 23))!=0)	// If the unique file attribute is set
+		{
+		if(aKeyword==EKeywordFile || aKeyword==EKeywordData)	// If the Keyword is File or Data
+			{
+				if(strlen(aFile->iFileName) > (KMaxFileName-KRofsMangleNameLength)) // check whether we have enough space to add the mangle tage
+					return Print(EError, "Lengthy filename with unique attribute to name mangle.\n");
+			}
+		else	// for all other keywords
+			return Print(EError, "exattrib field not allowed for entries except data and file.\n");
+		}
+	return KErrNone;
+	}
+
+
+TInt TRomNode::SetAtt(char *anAttWord)
+//
+// Set the file attribute byte from the letters passed
+//
+	{
+	iAtt=0;
+	if (anAttWord==0 || anAttWord[0]=='\0')
+		return Print(EError, "Missing argument for keyword 'attrib'.\n");
+	for (char *letter=anAttWord;*letter!=0;letter++)
+		{
+		switch (*letter)
+			{
+		case 'R':
+		case 'w':
+			iAtt |= KEntryAttReadOnly;
+			break;
+		case 'r':
+		case 'W':
+			iAtt &= ~KEntryAttReadOnly;
+			break;
+		case 'H':
+			iAtt |= KEntryAttHidden;
+			break;
+		case 'h':
+			iAtt &= ~KEntryAttHidden;
+			break;
+		case 'S':
+			iAtt |= KEntryAttSystem;
+			break;
+		case 's':
+			iAtt &= ~KEntryAttSystem;
+			break;
+		default:
+			return Print(EError, "Unrecognised attrib - '%c'.\n", *letter);
+			break;
+			}
+		}
+	return KErrNone;
+	}
+
+
+// Calculates the amount of ROM space required to hold
+// this entry. The return is the actual size of the TRofsEntry
+// structure, not rounded up
+TInt TRomNode::CalculateEntrySize() const {
+	UTF16String unistr(iName);
+	TInt requiredSizeBytes = KRofsEntryHeaderSize +	unistr.bytes();
+	return requiredSizeBytes;
+	}
+
+TInt TRomNode::CalculateDirectoryEntrySize( TInt& aDirectoryBlockSize,
+										    TInt& aFileBlockSize )
+	// Calculates the total size of the TRofsDir structure required
+	// for this directory and the size of the files block. Traverses all the
+	// children adding their entry sizes. The result is not rounded up.
+	//
+	// On return aDirectoryBlockSize is the number of bytes required for the
+	//	main directory structure. aFileBlockSize is the number of bytes
+	//	required to hold the list of files.
+	//
+	// Returns KErrNone on success
+	{
+
+	TInt offsetBytes=0;
+	TInt padBytes=0;
+	if( 0 == iTotalDirectoryBlockSize )
+		{
+		// need to calculate by walking children
+		if( !iChild )
+			{
+			return Print(EError, "TRomNode structure corrupt\n");
+			}
+
+		TInt dirBlockSize = KRofsDirHeaderSize;
+		TInt fileBlockSize = 0;
+		TInt fileCount=0;
+		TInt dirCount=0;
+
+		TRomNode* node = iChild;
+		while (node)
+			{
+			TInt entrySize = node->CalculateEntrySize();
+			if( node->IsDirectory() )
+				{
+				dirBlockSize += (4 - dirBlockSize) & 3;	// pad to next word boundary
+				dirBlockSize += entrySize;
+				dirCount++;
+				}
+			else
+				{
+				fileBlockSize += (4 - fileBlockSize) & 3;	// pad to next word boundary
+				fileBlockSize += entrySize;
+				fileCount++;
+				}
+			node = node->iSibling;
+			}
+
+		offsetBytes = ((fileCount + dirCount) * 2) + 4; //the +4 are the two offset counts,
+		padBytes = offsetBytes % 4;
+
+		iTotalDirectoryBlockSize = dirBlockSize;
+		iTotalFileBlockSize = fileBlockSize;
+		}
+
+	aDirectoryBlockSize = iTotalDirectoryBlockSize + offsetBytes + padBytes;
+	aFileBlockSize = iTotalFileBlockSize;
+	return KErrNone;
+	}
+
+/**
+Place the files and it's attributes (incase of executables)
+Called for both rofs and datadrive creation.
+
+@param aDest   - Destination buffer.
+@param aOffset - offset value, used for rofs only.
+@param aMaxSize- Maximum size required for rofs.
+
+@return - Returns the number of bytes placed or a -ve error code.
+*/
+TInt TRomNode::PlaceFile( TUint8* &aDest, TUint aOffset, TUint aMaxSize, CBytePair *aBPE ){
+	//
+	// Place the file into the ROM image, making any necessary conversions
+	// along the way.
+	//
+	// Returns the number of bytes placed or a -ve error code.
+	
+
+	TInt size=0;
+
+	// file hasn't been placed for drive image.
+	if(gDriveImage)
+	{
+		size = iEntry->PlaceFile(aDest,aMaxSize,aBPE);
+		iSize = size;
+	}
+	else
+	{
+		if (iEntry->iHidden)
+			iFileStartOffset = KFileHidden;
+		else
+		{
+                    if (iEntry->iFileOffset==0)
+                    {
+                        // file hasn't been placed
+                        size = iEntry->PlaceFile( aDest, aMaxSize, aBPE );
+                        if (size>=0)
+                            iEntry->iFileOffset = aOffset;
+                    }
+                    else {
+                        iFileStartOffset = (TInt)iEntry;
+                    }
+		}
+	}
+
+	// Deal with any override attributes
+	// (omit paging overrides as these are dealt with in TRomBuilderEntry::PlaceFile
+	//  and may also be legitimately specified for non-executable files in ROM)
+	if( iOverride&~(KOverrideCodeUnpaged|KOverrideCodePaged|KOverrideDataUnpaged|KOverrideDataPaged) )
+		{
+		E32ImageHeaderV* hdr = (E32ImageHeaderV*)aDest;
+
+		TUint hdrfmt = hdr->HeaderFormat();
+		if (hdrfmt != KImageHdrFmt_V)
+			{
+			Print(EError,"%s: Can't load old format binary\n", iEntry->iFileName);
+			return KErrNotSupported;
+			}
+
+		// First need to check that it's a real image header
+		if( (TUint)size > sizeof(E32ImageHeader) )
+			{
+			if( ((TInt)hdr->iSignature == 0x434f5045u) && ((TInt)hdr->iUid1 == KExecutableImageUidValue || (TInt)hdr->iUid1 == KDynamicLibraryUidValue) )
+				{
+				// Should check the CRC as well here...
+				// Something for later
+
+				// Ok, it looks like an image header
+				if( iOverride & KOverrideStack )
+					{
+					hdr->iStackSize = iStackSize;
+					}
+				if( iOverride & KOverrideHeapMin )
+					{
+					hdr->iHeapSizeMin = iHeapSizeMin;
+					}
+				if( iOverride & KOverrideHeapMax )
+					{
+					hdr->iHeapSizeMax = iHeapSizeMax;
+					}
+				if( iOverride & KOverrideFixed )
+					{
+					if( hdr->iFlags & KImageDll )
+						{
+						Print(EError,"%s: Can't used FIXED keyword on a DLL\n", iEntry->iFileName);
+						return KErrNotSupported;
+						}
+					hdr->iFlags |= KImageFixedAddressExe;
+					}
+				if( iOverride & (KOverrideUid1|KOverrideUid2|KOverrideUid3))
+					{
+					if (iOverride & KOverrideUid1)
+						{
+						hdr->iUid1 = iUid1;
+						}
+					if (iOverride & KOverrideUid2)
+						{
+						hdr->iUid2 = iUid2;
+						}
+					if (iOverride & KOverrideUid3)
+						{
+						hdr->iUid3 = iUid3;
+						}
+					// Need to re-checksum the UIDs
+					TUidType ut(TUidType(TUid::Uid(hdr->iUid1), TUid::Uid(hdr->iUid2), TUid::Uid(hdr->iUid3)));
+					hdr->iUidChecksum =  (checkSum(((TUint8*)&ut)+1)<<16)|checkSum(&ut);
+					}
+				if( iOverride & KOverridePriority )
+					{
+					hdr->iProcessPriority = (TUint16)iPriority;
+					}
+				if( iOverride & KOverrideCapability )
+					{
+					hdr->iS.iCaps = iCapability;
+					}
+
+				// Need to re-CRC the header
+				hdr->iHeaderCrc = KImageCrcInitialiser;
+				TUint32 crc = 0;
+				TInt hdrsz = hdr->TotalSize();
+				HMem::Crc32(crc, hdr, hdrsz);
+				hdr->iHeaderCrc = crc;
+				}
+			}
+		}
+
+	return size;
+	}
+
+TInt TRomNode::CountFileAndDir(TInt& aFileCount, TInt& aDirCount)
+	{
+	//
+	// Count the number of file and directory entries for this node
+	//
+	TRomNode* node = iChild;
+
+	aFileCount=0;
+	aDirCount=0;
+	while( node )
+		{
+		if( node->IsFile() )
+			{
+			aFileCount++;
+			}
+		else
+			{
+			aDirCount++;
+			}
+
+		node = node->iSibling;
+		}
+	return KErrNone;
+	}
+
+TInt TRomNode::Place( TUint8* aDestBase )
+	//
+	// Writes this directory entry out to the image.
+	// The image starts at aDestBase.
+	// The position in the image must already have been set with SetImagePosition()
+	// and SetFileBlockPosition().
+	// Returns KErrNone on success
+	//
+	{
+	TUint8* dirBlockBase = aDestBase + iImagePosition;
+	TUint8* fileBlockBase = aDestBase + iFileBlockPosition;
+
+	TRofsDir* pDir = (TRofsDir*)dirBlockBase;
+	pDir->iFirstEntryOffset = KRofsDirFirstEntryOffset;
+	pDir->iFileBlockAddress = iFileBlockPosition;
+	pDir->iFileBlockSize = iTotalFileBlockSize;
+	pDir->iStructSize = (TUint16)iTotalDirectoryBlockSize;
+
+	TRofsEntry* pDirEntry = &(pDir->iSubDir);
+	TRofsEntry* pFileEntry = (TRofsEntry*)fileBlockBase;
+
+	TInt dirCount;
+	TInt fileCount;
+	TInt index = 0;
+	CountFileAndDir(fileCount, dirCount);
+
+	SortableEntry* array = new SortableEntry[fileCount + dirCount];
+	TRomNode* node = iChild;
+
+	while( node )
+		{
+		TRofsEntry* entry;
+
+		if( node->IsFile() )
+			{
+			entry = pFileEntry;
+
+			//Offset in 32bit words from start of file block
+			array[index].iOffset = (TUint16) ((((TUint8*) entry) - fileBlockBase) >> 2);
+			array[index].iIsDir = EFalse;
+			}
+		else
+			{
+			entry = pDirEntry;
+
+			//Offset in 32bit words from start of directory block
+			array[index].iOffset = (TUint16) ((((TUint8*) entry) - dirBlockBase) >> 2);
+			array[index].iIsDir = ETrue;
+			}
+		array[index].iEntry = entry;
+		index++;	 
+		entry->iNameOffset = KRofsEntryNameOffset; 
+		entry->iAtt = node->iAtt;
+		entry->iAttExtra = node->iAttExtra;
+
+		TInt entryLen = KRofsEntryHeaderSize;
+		UTF16String unistr(node->iName);
+		if(!unistr.IsEmpty()){
+			entry->iNameLength = unistr.length();
+			memcpy(entry->iName,unistr.c_str(),unistr.bytes());
+			entryLen += unistr.bytes() ; 
+		}
+		entryLen += (4 - entryLen) & 3;	// round up to nearest word
+		entry->iStructSize = (TUint16)entryLen;
+
+		if( node->IsFile() )
+			{
+			// node is a file, entry points to the file
+			// write an entry out into the file block
+			pFileEntry->iFileAddress = node->iFileStartOffset;
+			node->iAtt &= ~KEntryAttDir;
+			pFileEntry->iFileSize = node->iEntry->RealFileSize();
+			memcpy(&pFileEntry->iUids[0], &node->iEntry->iUids[0], sizeof(pFileEntry->iUids));
+			pFileEntry = (TRofsEntry*)( (TUint8*)pFileEntry + entryLen );
+			}
+		else
+			{
+			// node is a subdirectory, entry points to directory
+			pDirEntry->iFileAddress = node->iImagePosition;
+			node->iAtt |= KEntryAttDir;
+
+			// the size is just the size of the directory block
+			pDirEntry->iFileSize = node->iTotalDirectoryBlockSize;
+			pDirEntry = (TRofsEntry*)( (TUint8*)pDirEntry + entryLen );
+			}
+
+		node = node->iSibling;
+		}
+
+	qsort(array,fileCount + dirCount,sizeof(SortableEntry),&compare);
+
+	//Now copy the contents of sorted array to the image
+	TUint16* currentPtr = (TUint16*) (dirBlockBase + iTotalDirectoryBlockSize);
+
+	*currentPtr=(TUint16)dirCount;
+	currentPtr++;
+	*currentPtr=(TUint16)fileCount;
+	currentPtr++;
+
+	for (index = 0; index < (fileCount + dirCount); index++)
+		{
+		*currentPtr = array[index].iOffset;
+		currentPtr++;
+		}
+	delete[] array;
+	return KErrNone;
+	}
+
+
+
+void TRomNode::Remove(TRomNode* aChild)
+	{
+	if (iChild==0)
+		{
+		Print(EError, "Removing file from a file!!!\n");
+		return;
+		}
+	if (iChild==aChild) // first child in this directory
+		{
+		iChild = aChild->iSibling;
+		aChild->iSibling = 0;
+		if(iChild==0)
+			{
+				iParent->Remove(this);
+				TRomNode * current = TheFirstNode;
+				TRomNode * prev = current;
+				while(current != this)
+					{
+						prev = current;
+						current = current->NextNode();
+					}
+				prev->SetNextNode(current->NextNode());
+				delete this;
+			}
+		return;
+		}
+	TRomNode* prev = iChild;
+	while (prev->iSibling && prev->iSibling != aChild)
+		prev = prev->iSibling;
+	if (prev==0)
+		{
+		Print(EError, "Attempting to remove file not in this directory!!!\n");
+		return;
+		}
+	prev->iSibling = aChild->iSibling;
+	aChild->iSibling = 0;
+	}
+
+void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount)
+	{
+	TRomNode *current=iChild;
+	while(current)
+		{
+		if (current->iChild)
+			aDirCount++;
+		else
+ 			aFileCount++;
+	current=current->iSibling;
+		}
+	}
+
+//
+// Follow the TRomNode tree, destroying it
+//
+void TRomNode::Destroy() {
+ 	TRomNode *current = this; // root has no siblings
+	while (current)
+		{
+		if (current->iChild)
+			current->iChild->Destroy();
+		TRomNode* prev=current;
+		current=current->iSibling;
+		delete prev;
+        prev = 0;
+		}
+ }
+
+ 
+
+ 
+void TRomNode::AddNodeForSameFile(TRomNode* aPreviousNode, TRomBuilderEntry* aFile)
+	{
+	// sanity checking
+	if (iNextNodeForSameFile != 0 || iEntry != aFile || (aPreviousNode && aPreviousNode->iEntry != iEntry))
+		{
+		Print(EError, "Adding Node for same file: TRomNode structure corrupted\n");
+		exit(666);
+		}
+	iNextNodeForSameFile = aPreviousNode;
+	}
+
+
+
+
+
+//**************************************
+// TRomBuilderEntry
+//**************************************
+
+
+//
+// Constructor
+//
+TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,const char *aName):
+iFirstDllDataEntry(0),	iName(0),iFileName(0),iNext(0), iNextInArea(0),
+iExecutable(EFalse), iFileOffset(EFalse), iCompressEnabled(0),
+iHidden(0), iRomNode(0), iRealFileSize(0)
+{
+	if (aFileName)
+   		iFileName = NormaliseFileName(aFileName);
+	if (aName)
+		iName = NormaliseFileName(aName);
+	memset(iUids,0 ,sizeof(TCheckedUid));
+}
+//
+// Destructor
+//
+TRomBuilderEntry::~TRomBuilderEntry() {
+	if(iFileName) {
+		delete []iFileName;
+		iFileName = 0;
+	}
+	
+	if(iName) {
+		delete []iName;
+		iName = 0 ;
+	}
+}
+
+void TRomBuilderEntry::SetRomNode(TRomNode* aNode)
+	{
+	aNode->AddNodeForSameFile(iRomNode, this);
+	iRomNode = aNode;
+	}
+
+//
+// Place the file in ROFS. Since we don't support compression yet all
+// we have to do is read the file into memory
+// compress it, if it isn't already compressed.
+//
+// Returns the number of bytes used, or -ve error code
+TInt TRomBuilderEntry::PlaceFile( TUint8* &aDest,TUint aMaxSize, CBytePair *aBPE ){
+
+
+	TUint compression = 0;
+	TBool executable = iExecutable;
+	Print(ELog,"Reading file %s to image\n", iFileName );
+	TUint32 size = HFile::GetLength(iFileName);
+	if (size==0)
+		Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",iFileName);
+	if (aDest == NULL) {
+		aMaxSize = size << 1;
+		aMaxSize = (aMaxSize>0) ? aMaxSize : 2;
+		aDest = new TUint8[aMaxSize];
+   }
+
+	if (executable)
+	{
+		// indicate if the image will overflow without compression
+		TBool overflow;
+		if(size>aMaxSize)
+			overflow = ETrue;
+		else
+			overflow = EFalse;
+
+		// try to compress this executable
+		E32ImageFile f(aBPE);
+		TInt r = f.Open(iFileName);
+		// is it really a valid E32ImageFile?
+		if (r != KErrNone)
+		{
+			Print(EWarning, "File '%s' is not a valid executable.  Placing file as data.\n", iFileName);
+			executable = EFalse;
+		}
+		else
+		{
+
+			if(iRomNode->iOverride & KOverrideDllData)
+			{
+				DllDataEntry *aDllEntry = iRomNode->iEntry->GetFirstDllDataEntry();
+				TLinAddr* aExportTbl;
+				void *aLocation;
+				TUint aDataAddr;
+				char *aCodeSeg, *aDataSeg;
+
+				aExportTbl = (TLinAddr*)((char*)f.iData + f.iOrigHdr->iExportDirOffset);
+
+				// const data symbol may belong in the Code section. If the address lies within the Code or data section limits,
+				// get the corresponding location and update it.While considering the Data section limits
+				// don't include the Bss section, as it doesn't exist as yet in the image.
+				while( aDllEntry ){
+					if(aDllEntry->iOrdinal != (TUint32)-1){
+						if(aDllEntry->iOrdinal < 1 || aDllEntry->iOrdinal > (TUint)f.iOrigHdr->iExportDirCount){
+							Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", aDllEntry->iOrdinal, iRomNode->iName);
+							aDllEntry = aDllEntry->NextDllDataEntry();
+							continue;
+						}
+
+						//	Get the address of the data field via the export table.
+						aDataAddr = (TInt32)(aExportTbl[aDllEntry->iOrdinal - 1] + aDllEntry->iOffset);
+						if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){
+							aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset);
+							aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase );
+							memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
+						}
+						else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){
+							aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset);
+							aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase );
+							memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
+						}
+						else
+						{
+							Print(EWarning, "Patchdata failed as address pointed by ordinal %d of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName);
+						}
+					}
+					else if(aDllEntry->iDataAddress != (TLinAddr)-1){
+						aDataAddr = aDllEntry->iDataAddress + aDllEntry->iOffset;
+						if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){
+							aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset);
+							aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase );
+							memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
+						}
+						else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){
+							aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset);
+							aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase );
+							memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
+						}
+						else
+						{
+							Print(EWarning, "Patchdata failed as address 0x%x of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName);
+						}
+					}
+					aDllEntry = aDllEntry->NextDllDataEntry();
+				}
+			}
+
+			compression = f.iHdr->CompressionType();
+			Print(ELog,"Original file:'%s' is compressed by method:%08x\n", iFileName, compression);
+
+
+			TUint32 oldFileComp;
+			TUint32 newFileComp;
+
+			if(compression)
+			{
+				// The E32 image in release directory is compressed
+				oldFileComp = compression;
+			}
+			else
+			{
+				// The E32 image in release directory is uncompressed
+				oldFileComp = 0;
+			}
+
+			if( iCompressEnabled != ECompressionUnknown)
+			{
+				// The new state would be as stated in obey file, i.e.
+				// filecompress or fileuncompress
+				newFileComp = gCompressionMethod;
+			}
+			else if (gCompress != ECompressionUnknown)
+			{
+				// The new state would be as stated set globally
+				newFileComp = gCompressionMethod;
+			}
+			else
+			{
+				// When not known if compression is to be applied or not,
+				// set it same as that of the E32 image in release directory
+				newFileComp = oldFileComp;
+			}
+
+			if(!gDriveImage)
+			{
+				// overide paging flags...
+				E32ImageHeaderV* h=f.iHdr;
+				if (iRomNode->iOverride & KOverrideCodePaged)
+				{
+					h->iFlags &= ~KImageCodeUnpaged;
+					h->iFlags |= KImageCodePaged;
+				}
+				if (iRomNode->iOverride & KOverrideCodeUnpaged)
+				{
+					h->iFlags |= KImageCodeUnpaged;
+					h->iFlags &= ~KImageCodePaged;
+				}
+				if (iRomNode->iOverride & KOverrideDataPaged)
+				{
+					h->iFlags &= ~KImageDataUnpaged;
+					h->iFlags |= KImageDataPaged;
+				}
+				if (iRomNode->iOverride & KOverrideDataUnpaged)
+				{
+					h->iFlags |= KImageDataUnpaged;
+					h->iFlags &= ~KImageDataPaged;
+				}
+
+				// apply global paging override...
+				switch(gCodePagingOverride)
+				{
+				case EKernelConfigPagingPolicyNoPaging:
+					h->iFlags |= KImageCodeUnpaged;
+					h->iFlags &= ~KImageCodePaged;
+					break;
+				case EKernelConfigPagingPolicyAlwaysPage:
+					h->iFlags |= KImageCodePaged;
+					h->iFlags &= ~KImageCodeUnpaged;
+					break;
+				case EKernelConfigPagingPolicyDefaultUnpaged:
+					if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
+						h->iFlags |= KImageCodeUnpaged;
+					break;
+				case EKernelConfigPagingPolicyDefaultPaged:
+					if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
+						h->iFlags |= KImageCodePaged;
+					break;
+				}
+				switch(gDataPagingOverride)
+				{
+				case EKernelConfigPagingPolicyNoPaging:
+					h->iFlags |= KImageDataUnpaged;
+					h->iFlags &= ~KImageDataPaged;
+					break;
+				case EKernelConfigPagingPolicyAlwaysPage:
+					h->iFlags |= KImageDataPaged;
+					h->iFlags &= ~KImageDataUnpaged;
+					break;
+				case EKernelConfigPagingPolicyDefaultUnpaged:
+					if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
+						h->iFlags |= KImageDataUnpaged;
+					break;
+				case EKernelConfigPagingPolicyDefaultPaged:
+					if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
+						h->iFlags |= KImageDataPaged;
+					break;
+				}
+				f.UpdateHeaderCrc();
+
+				// make sure paged code has correct compression type...
+				if(h->iFlags&KImageCodePaged)
+				{
+					if(newFileComp!=0)
+						newFileComp = KUidCompressionBytePair;
+				}
+			}
+
+			if ( oldFileComp != newFileComp )
+			{
+
+				if( newFileComp == 0)
+				{
+					Print(ELog,"Decompressing executable '%s'\n", iFileName);
+					f.iHdr->iCompressionType = 0;
+				}
+				else
+				{
+					Print(ELog,"Compressing executable '%s' with method:%08x\n", iFileName, newFileComp);
+					f.iHdr->iCompressionType = newFileComp;
+				}
+				f.UpdateHeaderCrc();
+				if (overflow)
+				{
+					// need to check if the compressed file will fit in the image
+					//TODO the checking will slow down the build process, should do it later along with the writing on aDest.
+					TUint32 compressedSize;
+					char * buffer = new char [size];
+#if defined(__LINUX__)
+					ostrstream os((char*)aDest, aMaxSize, (ios_base::openmode)(ios_base::out+ios_base::binary));
+#elif defined(__TOOLS2__) && defined (_STLP_THREADS)
+					ostrstream os((char*)buffer, size,(ios_base::out+ios_base::binary));
+#elif defined( __TOOLS2__)
+					ostrstream os((char*)buffer, size,(ios_base::out+ios_base::binary));
+#else
+					ostrstream os( (char*)buffer, size, (ios_base::out+ios_base::binary));
+#endif
+					os << f;
+					compressedSize = os.pcount();
+					delete[] buffer;
+					if (compressedSize <= aMaxSize)
+						overflow = EFalse;
+				}
+			}
+			if (overflow)
+			{
+				Print(EError, "Can't fit '%s' in image\n", iFileName);
+				Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize);
+				exit(667);
+			}
+
+			//try to use cached version where possible.
+			if(gCache && !gDriveImage && !(iRomNode->iAlias) && (iRomNode->iEntry->iExecutable) && !(iRomNode->iOverride & KOverrideDllData))
+			{
+				//retrive cached version.
+				size_t len = strlen(iFileName) + 1;
+				char* temp = (char*)_alloca(len);
+				memcpy(temp,iFileName,len);
+				CacheEntry* entryref = CacheManager::GetInstance()->GetE32ImageFileRepresentation(temp , compression); 
+				if(entryref)
+				{
+					size = entryref->GetCachedFileBufferLen();
+					memcpy(aDest, entryref->GetCachedFileBuffer(), size);
+					memcpy(aDest,f.iHdr,sizeof(E32ImageHeaderV));
+					compression = atoi(entryref->GetCachedFileCompressionID());
+					memcpy(&iUids[0], aDest, sizeof(iUids));
+					if (compression)
+						Print(ELog,"Compressed executable File '%s' size: %08x, mode:%08x\n", iFileName, size, compression);
+					else if (iExecutable)
+						Print(ELog,"Executable File '%s' size: %08x\n", iFileName, size);
+					else
+						Print(ELog,"File '%s' size: %08x\n", iFileName, size);
+					iRealFileSize = size;	// required later when directory is written
+
+					return size;
+				}
+			}
+
+#if defined(__TOOLS2__) && defined (_STLP_THREADS)
+			ostrstream os((char*)aDest, aMaxSize,(ios_base::out+ios_base::binary));
+#elif __TOOLS2__
+			ostrstream os((char*)aDest, aMaxSize, (_Ios_Openmode)(ios_base::out+ios_base::binary));
+#else
+			ostrstream os((char*)aDest, aMaxSize, (ios_base::out+ios_base::binary));
+#endif
+			os << f;
+			size = os.pcount();
+
+			//save the decompressed/recompressed executable into the cache if it's enabled.
+			if(gCache && !gDriveImage && !(iRomNode->iAlias) && (iRomNode->iEntry->iExecutable) && !(iRomNode->iOverride & KOverrideDllData))
+			{
+				CacheEntry* newentryref = new (nothrow) CacheEntry();
+				if(newentryref)
+				{
+					boost::filesystem::path originalfilepath(iFileName);
+					time_t originalcreationtime = last_write_time(originalfilepath);
+					newentryref->SetOriginalFileCreateTime(&originalcreationtime);
+					newentryref->SetOriginalFileCompression(f.iHdr->CompressionType());
+					size_t len = strlen(iFileName) + 1;					
+					char* originalfilename = (char*)_alloca(len);
+					memcpy(originalfilename,iFileName,len);
+					CacheManager::GetInstance()->NormalizeFilename(originalfilename);
+					newentryref->SetOriginalFilename(originalfilename); 
+					newentryref->SetCachedFileCompression(compression);
+					string cachedfilename(".rofs.");
+					cachedfilename += newentryref->GetCachedFileCompressionID();
+					cachedfilename += ".";
+					cachedfilename += iFileName;
+					size_t slashpos;
+					while(((slashpos=cachedfilename.find("/"))!=string::npos) || ((slashpos=cachedfilename.find("\\"))!=string::npos))
+						cachedfilename.replace(slashpos, 1, 1, '.');
+					cachedfilename.insert(0, "/");
+					cachedfilename.insert(0, CacheManager::GetInstance()->GetCacheRoot());
+					newentryref->SetCachedFilename(cachedfilename.c_str());
+					newentryref->SetCachedFileBuffer((char*)aDest, size);
+					try
+					{
+						size_t len = strlen(iFileName) + 1;
+						char* temp = (char*)_alloca(len);
+						memcpy(temp,iFileName,len);
+						CacheManager::GetInstance()->Invalidate(temp, newentryref); 
+					}
+					catch (CacheException ce)
+					{
+						Print(EWarning, "Cache brings up an exception (%s) when processes %s\r\n", ce.GetErrorMessage(), iFileName);
+					}
+				}
+			}
+
+			compression = f.iHdr->CompressionType();
+			memcpy(&iUids[0], aDest, sizeof(iUids));
+		}
+	}
+	if (!executable)
+	{
+		if ( size > aMaxSize )
+		{
+			Print(EError, "Can't fit '%s' in image\n", iFileName);
+			Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize);
+			exit(667);
+		}
+		size = HFile::Read(iFileName, (TAny *)aDest);
+		TUint32 Uidslen = (size > sizeof(iUids)) ? sizeof(iUids) : size;
+		memcpy(&iUids[0], aDest, Uidslen);
+	}
+
+	if (compression)
+		Print(ELog,"Compressed executable File '%s' size: %08x, mode:%08x\n", iFileName, size, compression);
+	else if (iExecutable)
+		Print(ELog,"Executable File '%s' size: %08x\n", iFileName, size);
+	else
+		Print(ELog,"File '%s' size: %08x\n", iFileName, size);
+	iCompressEnabled = compression;
+	iRealFileSize = size;	// required later when directory is written
+
+	return size;
+}
+
+
+TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable)
+	{
+
+	if (iHidden && iChild==0)
+		{
+		// Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure)
+		if (iSibling)
+			return iSibling->CopyDirectory(aLastExecutable);
+		else
+			return 0;
+		}
+
+	TRomNode* copy = new TRomNode(iName);
+	if(aLastExecutable==0)
+		aLastExecutable = copy;		// this must be the root of the structure
+	// recursively copy the sub-structures
+	if (iChild)
+		copy->iChild = iChild->CopyDirectory(aLastExecutable);
+	if (iSibling)
+		copy->iSibling = iSibling->CopyDirectory(aLastExecutable);
+	copy->Clone(this);
+	return copy;
+	}
+
+
+
+
+void TRomNode::Clone(TRomNode* aOriginal)
+	{
+	iAtt = aOriginal->iAtt;
+	iAttExtra = aOriginal->iAttExtra;
+	iEntry = aOriginal->iEntry;
+	iHidden = aOriginal->iHidden;
+	iFileStartOffset = aOriginal->iFileStartOffset;
+	iSize = aOriginal->iSize;
+	iParent = aOriginal->iParent;
+    iAlias = aOriginal->iAlias;
+	}
+
+
+void TRomNode::Alias(TRomNode* aNode)
+	{
+	  // sanity checking
+	if (aNode->iEntry == 0)
+	{
+		Print(EError, "Aliasing: TRomNode structure corrupted\n");
+		exit(666);
+	}
+	Clone(aNode);
+	iEntry = aNode->iEntry;
+	if (iEntry)
+		{
+		iEntry->SetRomNode(this);
+		}
+    iAlias = true;
+	}
+
+
+void TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, const char* aNewName) {
+	aOldParent->Remove(this);
+	aNewParent->Add(this);
+	delete [] iName;
+	size_t len = strlen(aNewName)+1;
+	iName = new char[len];
+	memcpy (iName, aNewName,len);
+}
+
+TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const
+	{
+	TInt l = 0;
+	// aIgnoreHiddenAttrib is used to find the complete file name length as
+	// in ROM of a hidden file.
+	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
+		l = iParent->FullNameLength() + 1;
+	l += strlen((const char*)iName);
+	return l;
+	}
+
+TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const
+	{
+	TInt l = 0;
+	TInt nl = strlen((const char*)iName);
+	// aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file.
+	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
+		l = iParent->GetFullName(aBuf);
+	char* b = aBuf + l;
+	if (l)
+		*b++ = '\\', ++l;
+	memcpy(b, iName, nl);
+	b += nl;
+	*b = 0;
+	l += nl;
+	return l;
+	}
+
+// Fuction to return first node in the patchdata linked list
+DllDataEntry *TRomBuilderEntry::GetFirstDllDataEntry() const
+{
+	if (iFirstDllDataEntry)
+	{
+		return iFirstDllDataEntry;
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
+// Fuction to set first node in the patchdata linked list
+void TRomBuilderEntry::SetFirstDllDataEntry(DllDataEntry *aDllDataEntry)
+{
+	iFirstDllDataEntry = aDllDataEntry;
+}
+void TRomBuilderEntry::DisplaySize(TPrintType aWhere)
+{
+	TBool aIgnoreHiddenAttrib = ETrue;
+	TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib);
+	char *aBuf = new char[aLen+1];
+	if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
+		{
+		iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib);
+		if(iFileName)
+			Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, RealFileSize(), (iRomNode->iHidden || iHidden)?"hidden":"", aBuf);
+		else
+			Print(aWhere, "%s\t%s\n", (iRomNode->iHidden || iHidden)?"hidden":"", aBuf);
+		}
+	else
+		{
+		if(iFileName)
+			Print(aWhere, "%s\t%d\n", iFileName, RealFileSize());
+		}
+
+}