diff -r 000000000000 -r 044383f39525 imgtools/romtools/readimage/src/rofs_image_reader.cpp --- /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<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; +}