imgtools/romtools/readimage/src/rofs_image_reader.cpp
changeset 0 044383f39525
child 590 360bd6b35136
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/readimage/src/rofs_image_reader.cpp	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,616 @@
+/*
+* Copyright (c) 2005-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 "common.h"
+#include "r_obey.h"
+#include "rofs_image_reader.h"
+#include "e32_image_reader.h"
+
+RofsImage::RofsImage(RCoreImageReader *aReader) : CCoreImage(aReader) ,
+iRofsHeader(0), iRofsExtnHeader(0),iAdjustment(0),  iImageType(RCoreImageReader::E_UNKNOWN)
+{
+}
+
+RofsImageReader::RofsImageReader(char* aFile) : ImageReader(aFile), iInputFile(0)
+{
+	iImageReader = new RCoreImageReader(aFile);
+	iImage = new RofsImage(iImageReader);
+}
+
+RofsImageReader::~RofsImageReader()
+{
+	if(iInputFile)
+		iInputFile->close();
+	delete iInputFile;
+	delete iImage;
+	delete iImageReader;
+}
+
+void RofsImageReader::SetSeek(streampos aOff, ios::seek_dir aStartPos)
+{
+	if(!iInputFile)
+		return;
+
+	iInputFile->seekg(aOff, aStartPos);
+}
+
+void RofsImageReader::ReadImage()
+{
+	if(!iImageReader->Open())
+	{
+		throw ImageReaderException((char*)(iImageReader->Filename()), "Failed to open Image File");
+	}
+}
+
+void RofsImageReader::Validate()
+{
+}
+
+TInt RofsImage::ProcessImage()
+{
+	int result = CreateRootDir();
+	if (result == KErrNone)
+	{
+		if (iReader->Open())
+		{
+			iImageType = iReader->ReadImageType();
+			if (iImageType == RCoreImageReader::E_ROFS)
+			{
+				iRofsHeader = new TRofsHeader;
+				result = iReader->ReadCoreHeader(*iRofsHeader);
+				if (result != KErrNone)
+					return result;
+				
+				SaveDirInfo(*iRofsHeader);
+				result = ProcessDirectory(0);
+			}
+#if defined(__TOOLS2__) || defined(__MSVCDOTNET__)
+			else if (iImageType == RCoreImageReader::E_ROFX)
+#else
+			else if (iImageType == RCoreImageReader::TImageType::E_ROFX)
+#endif
+			{
+				iRofsExtnHeader = new TExtensionRofsHeader ;
+				result = iReader->ReadExtensionHeader(*iRofsExtnHeader);
+				if(result != KErrNone)
+					return result;
+
+				long filePos = iReader->FilePosition();
+				iAdjustment = iRofsExtnHeader->iDirTreeOffset - filePos;
+
+				SaveDirInfo(*iRofsExtnHeader);
+				result = ProcessDirectory(iAdjustment);
+			}
+			else
+			{
+				result = KErrNotSupported;
+			}
+		}
+		else
+		{
+			result = KErrGeneral;
+		}
+	}
+
+	return result;
+}
+
+void RofsImageReader::ProcessImage()
+{
+	iImage->ProcessImage();
+	iRootDirEntry = iImage->RootDirectory();
+}
+
+void RofsImageReader::Dump()
+{
+	if( !((iDisplayOptions & EXTRACT_FILES_FLAG) || (iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG) ||
+		(iDisplayOptions & EXTRACT_FILE_SET_FLAG)) )
+	{
+		
+		MarkNodes();
+		if(iDisplayOptions & DUMP_HDR_FLAG)
+		{
+			DumpHeader();
+		}
+		if( (iDisplayOptions & DUMP_DIR_ENTRIES_FLAG) ||
+			(iDisplayOptions & DUMP_VERBOSE_FLAG) )
+		{
+			DumpDirStructure();
+			DumpFileAttributes();
+		}
+	}
+}
+
+void RofsImageReader::DumpHeader()
+{
+	*out << "Image Name................." << iImgFileName.c_str() << endl;
+
+	int aPos = 0;
+
+	if( ((RofsImage*)iImage)->iImageType == RCoreImageReader::E_ROFS)
+	{
+		*out << "ROFS Image" << endl;
+
+		*out << "Image Signature..........." ;
+		while(aPos < K_ID_SIZE)
+		{
+			*out << ((RofsImage*)iImage)->iRofsHeader->iIdentifier[aPos++];
+		}
+		*out << endl << endl;
+
+		TUint aTotalDirSz = ((RofsImage*)iImage)->iRofsHeader->iDirTreeSize +
+							((RofsImage*)iImage)->iRofsHeader->iDirFileEntriesSize;
+		(*out).width(8);
+
+		*out << "Directory block size: 0x" << hex << ((RofsImage*)iImage)->iRofsHeader->iDirTreeSize << endl;
+		*out <<	"File block size:      0x" << hex << ((RofsImage*)iImage)->iRofsHeader->iDirFileEntriesSize << endl;
+		*out << "Total directory size: 0x" << hex << ( aTotalDirSz ) << endl;
+		*out << "Total image size:     0x" << hex << ((RofsImage*)iImage)->iRofsHeader->iImageSize << endl;
+	}
+	else if(((RofsImage*)iImage)->iImageType == RCoreImageReader::E_ROFX)
+	{
+		*out << "Extension ROFS Image" << endl;
+		*out << "Image Signature..........." ;
+		while(aPos < K_ID_SIZE)
+		{
+			*out << ((RofsImage*)iImage)->iRofsExtnHeader->iIdentifier[aPos++];
+		}
+		*out << endl << endl;
+
+		TUint aTotalDirSz = ((RofsImage*)iImage)->iRofsExtnHeader->iDirTreeSize +
+						((RofsImage*)iImage)->iRofsExtnHeader->iDirFileEntriesSize;
+		out->width(8);
+
+		*out << "Directory block size: 0x" << hex << ((RofsImage*)iImage)->iRofsExtnHeader->iDirTreeSize << endl;
+		*out <<	"File block size:      0x" << hex << ((RofsImage*)iImage)->iRofsExtnHeader->iDirFileEntriesSize << endl;
+		*out << "Total directory size: 0x" << hex << ( aTotalDirSz ) << endl;
+		*out << "Total image size:     0x" << hex << ((RofsImage*)iImage)->iRofsExtnHeader->iImageSize << endl;
+	}
+}
+
+void RofsImageReader::DumpDirStructure()
+{
+	 
+	*out << "Directory Listing" << endl;
+	*out << "=================" << endl; 
+	iImage->Display(out);
+
+}
+
+void RofsImageReader::MarkNodes()
+{
+	TRomNode *aNode = iRootDirEntry->NextNode();
+
+	while( aNode )
+	{
+		if(aNode->iEntry)
+		{
+			if( ReaderUtil::IsExecutable(aNode->iEntry->iUids) )
+			{
+				aNode->iEntry->iExecutable = true;
+			}
+			else
+			{
+				aNode->iEntry->iExecutable = false;
+			}
+		}
+		aNode = aNode->NextNode();
+	}
+}
+
+void RofsImageReader::DumpFileAttributes()
+{
+	TRomNode *aNode = iRootDirEntry->NextNode();
+	E32ImageFile	aE32Img;
+	streampos		aFileOffset;
+	string			iPath;
+	
+	while( aNode )
+	{
+		if( aNode->IsFile() )
+		{
+			if( !iInputFile )
+			{
+				// Open the image file once and to access the E32 images within,#
+				// seek to the file offsets...
+				iInputFile = new ifstream( (char*)(iImageReader->Filename()), ios::binary|ios::in);
+				
+				if(!iInputFile->is_open())
+				{
+					throw ImageReaderException((char*)iImageReader->Filename(), "Failed to open file");
+				}
+			}
+
+			try 
+			{
+				if( aNode->iEntry->iExecutable)
+				{
+					aFileOffset = 0;
+					if( ((RofsImage*)iImage)->iImageType == RCoreImageReader::E_ROFX)
+					{
+						if((TUint)aNode->iEntry->iFileOffset > ((RofsImage*)iImage)->iRofsExtnHeader->iDirTreeOffset)
+						{
+							//This is set only for files within this extended ROFS
+							aFileOffset = aNode->iEntry->iFileOffset - ((RofsImage*)iImage)->iAdjustment;
+						}
+					}
+					else
+					{
+						//This is set only for files within ROFS
+						aFileOffset = aNode->iEntry->iFileOffset;
+					}
+
+					if( aFileOffset )
+					{
+						SetSeek(aFileOffset , ios::beg);
+						memset(&aE32Img, 0, sizeof(aE32Img));
+						aE32Img.Adjust(aNode->iSize);
+						aE32Img.iFileSize = aNode->iSize;
+						if( iInputFile->fail())
+						{
+							// Check why is the fail bit set causing all subsequent
+							// istream operations to fail.
+							// For now, clear the fail bit...
+							iInputFile->clear();
+						}
+						*iInputFile >> aE32Img;
+						if(aE32Img.iError != KErrNone)
+						{
+							throw int (0);
+						}
+					}
+				}
+			}
+			catch(...)
+			{
+				// Just in case this was't a valid E32 image and the E32 reader didn't 
+				// catch it...
+				
+				string aStr("Failed to read contents of ");
+				aStr.append((char*)aNode->iName);
+
+				throw ImageReaderException((char*)iImageReader->Filename(), (char*)aStr.c_str());
+			}
+
+			*out << "********************************************************************" << endl;
+			iPath.assign((char*)aNode->iName);	
+			GetCompleteNodePath(aNode,iPath,"/");
+			*out << "File........................" << iPath.c_str() << endl;
+			if( aNode->iEntry->iExecutable )
+			{
+				if(aFileOffset)
+				{
+					// When its an E32 Image...
+					E32ImageReader::DumpE32Attributes(aE32Img);
+					if( iDisplayOptions & DUMP_E32_IMG_FLAG){
+						if(stricmp(iE32ImgFileName.c_str(), (const char*)aNode->iName) == 0){
+							TUint aSectionOffset = aE32Img.iOrigHdr->iCodeOffset;
+							TUint* aCodeSection = (TUint*)(aE32Img.iData + aSectionOffset);
+							*out << "\nCode (Size=0x" << hex << aE32Img.iOrigHdr->iCodeSize << ")" << endl;
+							DumpData(aCodeSection, aE32Img.iOrigHdr->iCodeSize);
+
+							aSectionOffset = aE32Img.iOrigHdr->iDataOffset;
+							TUint* aDataSection = (TUint*)(aE32Img.iData + aSectionOffset);
+							if( aE32Img.iOrigHdr->iDataSize){
+								*out << "\nData (Size=0x" << hex << aE32Img.iOrigHdr->iDataSize << ")" << endl;
+								DumpData(aDataSection, aE32Img.iOrigHdr->iDataSize);
+							}
+						}
+					}
+				}
+				else
+				{
+					*out << "Image "<< aNode->iName << " not in the extended ROFS " << iImgFileName.c_str() << endl;
+				}
+			}
+		}
+
+		aNode = aNode->NextNode();
+	}
+}
+
+
+/** 
+Function iterates through all the entries in the image.If the entry is a file,
+then it makes a call to GetFileExtension to check for the extension.
+
+@internalComponent
+@released
+*/
+void RofsImageReader::ExtractImageContents()
+{
+	if( (iDisplayOptions & EXTRACT_FILE_SET_FLAG) )
+	{
+		ImageReader::ExtractFileSet(NULL);
+	}
+
+	if( iDisplayOptions & EXTRACT_FILES_FLAG || iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG  )
+	{
+		// get the next Node 
+		TRomNode *nextNode = iRootDirEntry->NextNode();
+		// current Node.
+		TRomNode *currNode = iRootDirEntry;
+		// name of the log file.
+		string  logFile;
+		// output stream for the log file.
+		ofstream oFile;
+
+		if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG ){		 
+			if( ImageReader::iZdrivePath.compare("")){
+				// create a string to hold path information.
+				string filePath;
+				string delimiter;
+				delimiter.assign("\\");
+				filePath.assign( ImageReader::iZdrivePath );
+				// replace backslash with double backslash. 
+				FindAndInsertString(filePath,delimiter,delimiter);
+				logFile.assign(filePath);
+				// create specified directory.
+				CreateSpecifiedDir(&filePath[0],"\\\\");
+				logFile.append("\\\\");
+				logFile.append(ImageReader::iLogFileName);
+			}
+			else {				
+				logFile.assign(ImageReader::iLogFileName);
+			}
+
+			// open the specified file in append mode.
+			oFile.open(logFile.c_str(),ios::out|ios::app);
+
+			if(!oFile.is_open()) {
+				throw ImageReaderException((char*)ImageReader::iLogFileName.c_str(), "Failed to open the log file");
+			}
+		}
+
+		while( nextNode ){
+			if(nextNode->IsDirectory())	{
+				// if next node is a directory set current node as next node.
+				currNode = nextNode;
+			}
+			else {
+				// get file extension
+				CheckFileExtension((char*) nextNode->iName,nextNode->iEntry,currNode,oFile);
+			}
+			nextNode = nextNode->NextNode();
+		}
+
+		if(oFile.is_open()) oFile.close(); 
+
+	}
+}
+
+
+/** 
+Function to get check extension of the given file.If the extension of the file is "sis"
+then call ExtractFile function to extract the file from the image.  
+
+@internalComponent
+@released
+
+@param aFile	- file name. 
+@param aEntry	- entry of the file in image.
+@param aNode	- current node.
+@param aLogFile	- output stream.
+*/
+void RofsImageReader::CheckFileExtension(char* aFileName,TRomBuilderEntry* aEntry,TRomNode* aNode,ofstream& aLogFile)
+{
+	//create a string to hold path information.
+	string path;
+	// check whether the node has parent 
+	if(aNode->GetParent())
+	{
+		// get the complete path 
+		path.assign( (char*)aNode->iName );
+		GetCompleteNodePath( aNode, path, "\\\\" );
+	}
+	else
+	{
+		// else path is the current path
+		path.assign("");
+	}
+	if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG && iDisplayOptions & EXTRACT_FILES_FLAG )
+	{
+	 
+		size_t pos = string(aFileName).find_last_of(".");
+
+		const char* extName = "";
+		if(pos != string::npos)
+			extName = aFileName + pos + 1;	 
+		if ( 0 == stricmp(extName,"SIS") || 0 == stricmp(extName,"DAT")) {
+			// if the two strings are same then extract the corresponding file.
+			ImageReader::ExtractFile(aEntry->iFileOffset,aEntry->RealFileSize(),aFileName,path.c_str(),&ImageReader::iZdrivePath[0]);
+		}
+		else {
+			// log the entry path information on to the specified file.
+			WriteEntryToFile(aFileName,aNode,aLogFile);
+		}	 
+	}
+	else if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG ) {
+		// log the entry path information on to the specified file.
+		WriteEntryToFile(aFileName,aNode,aLogFile);
+	}
+	else {
+		// if the two strings are same then extract the corresponding file.
+		ImageReader::ExtractFile(aEntry->iFileOffset,aEntry->RealFileSize(),aFileName,path.c_str(),&ImageReader::iZdrivePath[0]);
+	}
+}
+
+/** 
+Function to get the complete path information of a file from an image.
+
+@internalComponent
+@released
+
+@param aNode	- starting offset of the file in the image.
+@param aName	- name of the current entry in the image.
+@param aAppStr	- string to append.
+@return - returns full path of the given file.
+*/
+void RofsImageReader::GetCompleteNodePath(TRomNode* aNode,string& aName,char* aAppStr)
+{
+	// check if the entry has a parent.
+	TRomNode* NodeParent = aNode->GetParent();
+	if(NodeParent)
+	{
+		string str( (char*)NodeParent->iName );
+		str.append( aAppStr );
+		str.append( aName );
+		aName = str;
+		GetCompleteNodePath(NodeParent,aName,aAppStr);
+	}
+}
+
+
+/** 
+Function to write the rom entry to an output stream.
+
+@internalComponent
+@released
+
+@param aNode		- starting offset of the file in the image.
+@param aFileName	- name of the current entry in the image.
+@param aLogFile		- output stream.
+*/
+void RofsImageReader::WriteEntryToFile(char* aFileName,TRomNode* aNode,ofstream& aLogFile)
+{
+	//create a string to hold path information.
+	string path;
+	
+	if(aNode->GetParent())
+	{
+		// get the complete path 
+		path.assign( (char*)aNode->iName );
+		GetCompleteNodePath( aNode, path, "\\" );
+	}
+	else
+	{
+		// else path is the current path
+		path.assign("");
+	}
+	
+	if(aLogFile.is_open())
+	{
+		aLogFile.seekp(0,ios::end);
+		aLogFile<<path.c_str()<<"\\"<<aFileName<<"\n";
+	}
+}
+
+/** 
+Function to get the directory structure information.
+
+@internalComponent
+@released
+
+@param aFileMap		- map of filename with its size and offset values.
+*/
+void RofsImageReader::GetFileInfo(FILEINFOMAP &aFileMap)
+{
+	// get the next Node 
+	TRomNode *nextNode = iRootDirEntry->NextNode();
+	// current Node.
+	TRomNode *currNode = iRootDirEntry;
+	// image size
+	TUint32 imgSize = GetImageSize();
+
+	while(nextNode)
+	{
+		if(nextNode->IsDirectory())
+		{
+			// if next node is a directory set current node as next node.
+			currNode = nextNode;
+		}
+		else
+		{
+			PFILEINFO fileInfo = new FILEINFO;
+			//create a string to hold path information.
+			string fileName;
+			TUint32 aFileOffset = 0;
+
+			// check whether the node has parent 
+			if(currNode->GetParent())
+			{
+				if( !((currNode->GetParent() == currNode->FirstNode()) && !(currNode->IsDirectory())) )
+				{
+					// get the complete path 
+					fileName.assign( (char*)currNode->iName );
+					GetCompleteNodePath( currNode, fileName, (char*)DIR_SEPARATOR );
+				}
+			}
+			else
+			{
+				// else path is the current path
+				fileName.assign("");
+			}
+			fileName.append(DIR_SEPARATOR);
+			fileName.append((char*)nextNode->iName);
+
+			// get the size of the entity.
+			fileInfo->iSize = nextNode->iEntry->RealFileSize();
+
+			// get the offset of the entity.
+			if( ((RofsImage*)iImage)->iImageType == RCoreImageReader::E_ROFX)
+			{
+				if((TUint)nextNode->iEntry->iFileOffset > ((RofsImage*)iImage)->iRofsExtnHeader->iDirTreeOffset)
+				{
+					//This is set only for files within this extended ROFS
+					aFileOffset = nextNode->iEntry->iFileOffset - ((RofsImage*)iImage)->iAdjustment;
+				}
+			}
+			else
+			{
+				//This is set only for files within ROFS
+				aFileOffset = nextNode->iEntry->iFileOffset;
+			}
+
+			fileInfo->iOffset = aFileOffset;
+
+			if((!fileInfo->iOffset) || ((fileInfo->iOffset + fileInfo->iSize) > imgSize))
+			{
+				fileInfo->iOffset = 0;
+				fileInfo->iSize = 0;
+			}
+
+			aFileMap[fileName] = fileInfo;
+		}
+
+		nextNode = nextNode->NextNode();
+	}
+}
+
+/** 
+Function to get the ROFS image size.
+
+@internalComponent
+@released
+*/
+TUint32 RofsImageReader::GetImageSize()
+{
+	TUint32 result = 0;
+
+	if( ((RofsImage*)iImage)->iImageType == RCoreImageReader::E_ROFS)
+	{
+		result = ((RofsImage*)iImage)->iRofsHeader->iImageSize;
+	}
+	else if(((RofsImage*)iImage)->iImageType == RCoreImageReader::E_ROFX)
+	{
+		result = ((RofsImage*)iImage)->iRofsExtnHeader->iImageSize;
+	}
+
+	return result;
+}