diff -r c7c26511138f -r 360bd6b35136 imgtools/romtools/rofsbuild/r_coreimage.cpp --- a/imgtools/romtools/rofsbuild/r_coreimage.cpp Wed Jun 16 16:51:40 2010 +0300 +++ b/imgtools/romtools/rofsbuild/r_coreimage.cpp Wed Jun 23 16:56:47 2010 +0800 @@ -1,699 +1,614 @@ -/* -* Copyright (c) 2003-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: -* -*/ - - -#include -#include "h_utl.h" - -#include -#include -#include "rofs.h" - -#include "r_obey.h" -#include "r_coreimage.h" - -// ----------------------------------------------------------- -// RCoreImageReader -// ----------------------------------------------------------- - -/** -Constructs reader for the specified file. - -@param aFilename Filename for core image file -*/ - RCoreImageReader::RCoreImageReader(char* aFilename) : - iImageType(E_UNKNOWN), iCoreImage(0), iFilename(aFilename) - { - } - -/** -Closes the core image file if it was opened. -*/ -RCoreImageReader::~RCoreImageReader() - { - if (iCoreImage) - fclose(iCoreImage); - iCoreImage = 0; - } - -/** -Opens the image file that was specified at construction. - -@return ETrue if file was opened successfully otherwise returns EFalse -*/ -TBool RCoreImageReader::Open() - { - iCoreImage = fopen(iFilename, "rb"); - if (!iCoreImage) - { - Print(EError, "Cannot open image file %s\n", iFilename); - return EFalse; - } - return ETrue; - } - -/** -Reads the image type from the core image file. It reads the value from the -file and then translates it into the internal enum used for processing -the images. - -@return Image type -*/ -RCoreImageReader::TImageType RCoreImageReader::ReadImageType() - { - iImageType = E_UNKNOWN; - if ( ReadIdentifier() == KErrNone) - { - if (iIdentifier[0] == 'R' && - iIdentifier[1] == 'O' && - iIdentifier[2] == 'F') - { - if (iIdentifier[3] == 'S') - iImageType = E_ROFS; - else if (iIdentifier[3] == 'x') - iImageType = E_ROFX; - } - } - return iImageType; - } - -/** -Reads the 4 byte image type identifier from the core image file. - -@return KErrNone for successful read or error number if failed -*/ -TInt RCoreImageReader::ReadIdentifier() - { - int itemsRead = fread(&iIdentifier, sizeof(TUint8), K_ID_SIZE, iCoreImage); - TInt result = ImageError(itemsRead, K_ID_SIZE, "Read Identifier"); - if (result != KErrNone) - { - iIdentifier[0] = 0; - } - return result; - } - -/** -Reads the core header from the image file. - -@param aHeader space for the header read from the file. Only valid if KErrNone is returned. -@return KErrNone for successful read or error number if failed -*/ -TInt RCoreImageReader::ReadCoreHeader(TRofsHeader& aHeader) - { - int itemsRead = fread (&aHeader.iHeaderSize, - (sizeof(TRofsHeader)) - K_ID_SIZE*sizeof(TUint8), 1, iCoreImage); - TInt result = ImageError(itemsRead, 1, "Read Core Header"); - if (result == KErrNone) - { - // copy the previously read identifier into the header - for (int i=0; iFilename(); - int result = CreateRootDir(); - if (result == KErrNone) - { - if (iReader->Open()) - { - RCoreImageReader::TImageType imageType = iReader->ReadImageType(); - if (imageType == RCoreImageReader::E_ROFS) - { - TRofsHeader header; - result = iReader->ReadCoreHeader(header); - if (result == KErrNone) - { - SaveDirInfo(header); - result = ProcessDirectory(0); - } - } - else - result = KErrNotSupported; - } - else - result = KErrGeneral; - } - return result; - } - -/** -Processes the directory in the core image file. - -@param aAdjustment The difference between offsets in the core image directory and -@return KErrNone for successful read or error number if failed -*/ -TInt CCoreImage::ProcessDirectory(long aAdjustment) - { - long filePos = iDirTreeOffset - aAdjustment; - TDirectoryEntry *firstDir = new TDirectoryEntry(filePos, iReader, iRootDirectory); - if (firstDir == 0) - return KErrNoMemory; - TInt result = firstDir->Process(aAdjustment); - delete firstDir; - return result; - } - -/** -Saves directory information from core image header for later usage. - -@param aHeader Header containing information to be saved -*/ -void CCoreImage::SaveDirInfo(TRofsHeader& aHeader) - { - iDirTreeOffset = aHeader.iDirTreeOffset; - iDirTreeSize = aHeader.iDirTreeSize; - iDirFileEntriesOffset = aHeader.iDirFileEntriesOffset; - iDirFileEntriesSize = aHeader.iDirFileEntriesSize; - iImageSize = aHeader.iMaxImageSize; - } - -/** -Saves directory information from extension image header for later usage. - -@param aHeader Header containing information to be saved -*/ -void CCoreImage::SaveDirInfo(TExtensionRofsHeader& aHeader) - { - iDirTreeOffset = aHeader.iDirTreeOffset; - iDirTreeSize = aHeader.iDirTreeSize; - iDirFileEntriesOffset = aHeader.iDirFileEntriesOffset; - iDirFileEntriesSize = aHeader.iDirFileEntriesSize; - iImageSize = aHeader.iMaxImageSize; - } - -/** -Displays the directory tree. This is used for debug purposes only. -*/ -void CCoreImage::Display(ostream* aOut) - { - iRootDirectory->DisplayStructure(aOut); - } - -/** -Reads offset where directory tree starts in core image. - -@return offset of directory tree in image -*/ -long CCoreImage::DirTreeOffset() - { - return iDirTreeOffset; - } - -TRomNode* CCoreImage::CopyDirectory(TRomNode*& aSourceDirectory) - { - return iRootDirectory->CopyDirectory(aSourceDirectory); - } - -TRomNode* CCoreImage::RootDirectory() - { - return iRootDirectory; - } - -void CCoreImage::SetRootDirectory(TRomNode* aDir) - { - iRootDirectory = aDir; - } - -TText* CCoreImage::RomFileName() - { - return iRomFileName; - } - -TInt CCoreImage::Size() - { - return iImageSize; - } - -// ----------------------------------------------------------- -// TDirectoryEntry -// ----------------------------------------------------------- - -/** -Initialises the directory entry - -@param aFilePos Position within file where the directory entry is located -@param aReader Handle used to access the file; -@param aDir The TRomNode associated with this directory -*/ -TDirectoryEntry::TDirectoryEntry(long aFilePos, RCoreImageReader* aReader, - TRomNode* aDir) : - iReader(aReader), iCurrentDir(aDir),iFilePos(aFilePos), - iAdjustment(0) - { - } - -/** -Empty destructor. -*/ -TDirectoryEntry::~TDirectoryEntry() - { - } - -/** -Processes the current directory entry. If the directory has any files it will -create the appropriate file entries in the directory tree. If the directory -has any subdirectories it will create nodes in the directory tree and will -create an TDirectoryEntry and then use that to process the subdirectory - -@param aAdjustment The difference between offsets in the core image directory and -the actual position in the file -*/ -TInt TDirectoryEntry::Process(long aAdjustment) - { - TRofsDir dir; - iAdjustment = aAdjustment; - long dirStartPos = iFilePos; - int result = KErrNone; - int dirSize = iReader->ReadDirEntry(dir, iFilePos); - if (dirSize != 0) - { - if (dir.iFileBlockAddress != 0) - { - // directory has files in it - result = AddFiles(dir.iFileBlockAddress-iAdjustment, dir.iFileBlockSize); - } - if (result == KErrNone && dir.iStructSize > dirSize) - { - // directory has subdirectories - result = AddSubDirs(dirStartPos + dir.iStructSize); - } - } - else - result = KErrGeneral; - - return result; - } - -/** -Processes the subdirectories in the current directory. For each subdirectory -a TDirectoryEntry is created and is then used to process the directory - -@param aEndDirPos Position where the directory block finishes. This is to determine when all subdirectories have been processed -*/ -TInt TDirectoryEntry::AddSubDirs(long aEndDirPos) - { - TRofsEntry entry; - iFilePos = iReader->FilePosition(); - TInt result = KErrNone; - while (iFilePos < aEndDirPos && result == KErrNone) - { - TInt size = iReader->ReadRofEntry(entry, iFilePos); - if (size >0) - { - TText* nameStr = GetName(entry.iName[0], entry.iNameLength); - if (nameStr !=0) - { - TRomNode *dir = iCurrentDir->NewSubDir(nameStr); - TDirectoryEntry *subDir = new TDirectoryEntry( - entry.iFileAddress-iAdjustment, iReader, dir); - if (subDir != 0) - { - // now process the subdirectory - subDir->Process(iAdjustment); - iFilePos += entry.iStructSize; - // round to nearest word boundary - iFilePos += (4-entry.iStructSize) & 3; - } - else - result = KErrNoMemory; - - if (subDir) - { - delete subDir; - } - } - else - result = KErrNoMemory; - if(nameStr != 0) - delete [] nameStr; - } - else - { - result = KErrGeneral; - } - } - return result; - } - -/** -Processes a file entries block in the directory and creates the appropriate -nodes for each file in the block - -@param aStartPosition start for file block in the core image file -@param aSize size of the file entries block -*/ -TInt TDirectoryEntry::AddFiles(long aStartPosition, int aSize ) - { - long savedPosition = iReader->FilePosition(); - long currentPos = aStartPosition; - iReader->SetFilePosition(aStartPosition); - long endPos = aStartPosition+aSize; - TRofsEntry entry; - TInt result = KErrNone; - while (currentPos < endPos && result == KErrNone) - { - TInt size = iReader->ReadRofEntry(entry, currentPos); - if (size > 0) - { - TText *nameStr = GetName(entry.iName[0], entry.iNameLength); - if (nameStr != 0) - { - result = CreateFileEntry(nameStr, entry); - currentPos += entry.iStructSize; - } - else - result = KErrNoMemory; - if(nameStr != 0) - delete [] nameStr; - } - else - { - result = KErrGeneral; - } - } - iReader->SetFilePosition(savedPosition); - return result; - } - -/** -Creates a new node for a file entry and the associated TRomBuilderEntry. - -@param aNameStr Name of the file entry to be created -@param aFileAddress Address of file in the core image -@param aFileSize Size of the file -*/ -TInt TDirectoryEntry::CreateFileEntry(TText* aNameStr, TRofsEntry& aRofsEntry) - { - TRomBuilderEntry *fileEntry = new TRomBuilderEntry(0,aNameStr); - if (fileEntry == 0) - return KErrNoMemory; - - memcpy(&fileEntry->iUids[0], &aRofsEntry.iUids[0], sizeof(fileEntry->iUids)); - fileEntry->iFileOffset = aRofsEntry.iFileAddress; - fileEntry->SetRealFileSize(aRofsEntry.iFileSize); - TRomNode *file = new TRomNode(aNameStr, fileEntry); - file->iSize = aRofsEntry.iFileSize; - if (file == 0) - { - delete fileEntry; - return KErrNoMemory; - } - file->iAtt = aRofsEntry.iAtt; - file->iAttExtra = aRofsEntry.iAttExtra; - iCurrentDir->AddFile(file); - return KErrNone; - } - -/** -Gets the name of a file or directory from the core image. The first character -of the name has already been read. - -@param aFirstChar first character of name (already read by TRofsEntry) -@param aLength Length of name to be read (including the first character) -*/ -TText* TDirectoryEntry::GetName(TUint16 aFirstChar, TInt aLength) - { - TText *nameStr = 0; - TUint16* name = new TUint16[aLength]; - if (name !=0) - { - name[0] = aFirstChar; - TInt result = iReader->ReadRofEntryName(&name[1], aLength-1); - if (result == KErrNone) - { - nameStr = new TText[aLength+1]; - if (nameStr != 0) - { - for (int i=0; i< aLength; i++) - { - nameStr[i] = (TText) name[i]; - } - nameStr[aLength]=0; - } - } - delete [] name; - } - return nameStr; - } - +/* +* Copyright (c) 2003-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: +* +*/ + + +#include +#include "h_utl.h" + +#include +#include +#include "rofs.h" + +#include "r_obey.h" +#include "r_coreimage.h" +#include "utf16string.h" +// ----------------------------------------------------------- +// RCoreImageReader +// ----------------------------------------------------------- + +/** +Constructs reader for the specified file. + +@param aFilename Filename for core image file +*/ +RCoreImageReader::RCoreImageReader(const char* aFilename) : +iImageType(E_UNKNOWN), iFilename(aFilename) { +} + +/** +Closes the core image file if it was opened. +*/ +RCoreImageReader::~RCoreImageReader() { + if (iCoreImage.is_open()) + iCoreImage.close(); +} + +/** +Opens the image file that was specified at construction. + +@return ETrue if file was opened successfully otherwise returns EFalse +*/ +TBool RCoreImageReader::Open() { + if(iCoreImage.is_open()) { + iCoreImage.seekg(0,ios_base::beg); + }else{ + iCoreImage.open(iFilename.c_str(), ios_base::in + ios_base::binary); + if (!iCoreImage.is_open()) { + Print(EError, "Cannot open image file %s\n", iFilename.c_str()); + return EFalse; + } + } + + return ETrue; +} + +/** +Reads the image type from the core image file. It reads the value from the +file and then translates it into the internal enum used for processing +the images. + +@return Image type +*/ +RCoreImageReader::TImageType RCoreImageReader::ReadImageType() { + iImageType = E_UNKNOWN; + iCoreImage.seekg(0,ios_base::beg); + if ( ReadIdentifier() == KErrNone) { + if (iIdentifier[0] == 'R' && + iIdentifier[1] == 'O' && + iIdentifier[2] == 'F') { + if (iIdentifier[3] == 'S') + iImageType = E_ROFS; + else if (iIdentifier[3] == 'x') + iImageType = E_ROFX; + } + } + return iImageType; +} + +/** +Reads the 4 byte image type identifier from the core image file. + +@return KErrNone for successful read or error number if failed +*/ +TInt RCoreImageReader::ReadIdentifier() { + + iCoreImage.read(reinterpret_cast(&iIdentifier[0]),K_ID_SIZE); + TInt result = ImageError(iCoreImage.gcount(), K_ID_SIZE, "Read Identifier"); + if (result != KErrNone) { + iIdentifier[0] = 0; + } + return result; +} + +/** +Reads the core header from the image file. + +@param aHeader space for the header read from the file. Only valid if KErrNone is returned. +@return KErrNone for successful read or error number if failed +*/ +TInt RCoreImageReader::ReadCoreHeader(TRofsHeader& aHeader) { + int bytesRead = sizeof(TRofsHeader) - K_ID_SIZE; + iCoreImage.read(reinterpret_cast(&aHeader.iHeaderSize),bytesRead ); + TInt result = ImageError(iCoreImage.gcount(),bytesRead, "Read Core Header"); + if (result == KErrNone) { + // copy the previously read identifier into the header + for (int i=0; i(&aHeader.iHeaderSize),bytesRead); + TInt result = ImageError(iCoreImage.gcount(),bytesRead, "Read Extension Header"); + if (result == KErrNone) { + // copy the previously read identifier into the header + for (int i=0; i(&dummy), sizeof(dummy)); + int bytesRead = iCoreImage.gcount(); + if(bytesRead == sizeof(dummy) && !iCoreImage.fail() || !iCoreImage.eof()) + valid = ETrue; + } + iCoreImage.seekg(currentPos, ios_base::beg); // return to previous position + return valid; +} + +/** +Reads a directory entry from the current position in the core image file. This +method does not read the variable length TRofsEntry part of the directory entry. +TRofsEntry does not exist for all directory entries. This is read later by +other methods + +@param aDir memory where the directory entry is read from the file. This is only valid if KErrNone is returned. +@return KErrNone for successful read or error number if failed +*/ +TInt RCoreImageReader::ReadDirEntry(TRofsDir& aDir) { + // read directory without the associated TRofsEntry. The TRofsEntry + // is read later when handling subdirectories + int bytesRead = sizeof(TRofsDir) - sizeof(TRofsEntry); + iCoreImage.read(reinterpret_cast(&aDir), bytesRead); + if (ImageError(iCoreImage.gcount(), bytesRead, "Read Dir") == KErrNone) + return bytesRead; + else + return 0; +} + +/** +Reads a directory entry from the specified position in the core image file. +This method moves the position of the file to the specified value and then +uses the other ReadDirEntry method to read the directory entry + +@param aDir memory where the directory entry is read from the file. This is only valid if KErrNone is returned. +@param aFilePos position in the core image file where the directory +entry is located +@return KErrNone for successful read or error number if failed +@see RCoreImageReader::ReadDirEntry(TRofsDir* aDir) +*/ +TInt RCoreImageReader::ReadDirEntry(TRofsDir& aDir, size_t aFilePos) { + SetFilePosition(aFilePos); + return ReadDirEntry(aDir); +} + +/** +Reads a TRofsEntry from the current file position within the core image. + +@param aEntry memory to be used for reading the data from the file. This is only valid if the size returned is greater than zero +@return size of the entry read +*/ +TInt RCoreImageReader::ReadRofEntry(TRofsEntry& aEntry) { + // need to work out how big entry needs to be from the Struct Size + // in TRofsEntry + iCoreImage.read(reinterpret_cast(&aEntry.iStructSize), sizeof(TUint16)); + int result = ImageError(iCoreImage.gcount(), sizeof(TUint16), "Read Entry Size"); + if (result == KErrNone) { + // read rest of entry excluding the iStructSize + int bytesRead = sizeof(TRofsEntry) -sizeof(TUint16); + iCoreImage.read(reinterpret_cast(&aEntry.iUids[0]),bytesRead); + result = ImageError(iCoreImage.gcount(), bytesRead, "Rest of Entry"); + // return length read - this include includes iStructSize and first char of name + if (result == KErrNone) + return sizeof(TRofsEntry); + } + return 0; +} + +/** +Reads a TRofsEntry from the specified position within the core image + +@param aEntry memory to be used for reading the data from the file. This is only valid if the size returned is greater than zero +@param aFilePos position in the core image file where the entry is located +@return size of the entry read +*/ +TInt RCoreImageReader::ReadRofEntry(TRofsEntry& aEntry, size_t aFilePos) { + SetFilePosition(aFilePos); + return ReadRofEntry(aEntry); +} + +/** +Reads a name of the specified length from the core image file. + +@param aName memory for the name read from the file. Only valid if KErrNone is returned +@param aLength length of name to be read +@return KErrNone for successful read or error number if failed +*/ +TInt RCoreImageReader::ReadRofEntryName(TUint16* aName, int aLength) { + int bytesRead = aLength << 1; + iCoreImage.read(reinterpret_cast(aName), bytesRead); + return ImageError(iCoreImage.gcount(), bytesRead, "Rof Entry Name"); +} + +/** +Provides the current file position in the core image file. + +@return Current file position +*/ +size_t RCoreImageReader::FilePosition() { + return iCoreImage.tellg(); +} + +/** +Provides the name of the core image file being read. + +@return Core image Filename +*/ +const char* RCoreImageReader::Filename() const { + return iFilename.c_str(); +} + +/** +Determines whether the last read from the file was valid or not. +It checks that the number of items read where the same number as expected, +that there are no file errors and that the end of file was not reached. If an +error is found than a message is printed and the appropriate error number is +returned. + +@param aItemsRead Number of items read +@param aExpected Number of items expected to have been read +@param aInfo Used by the caller to identify where the error occurred. +@return Error number. KErrNone is returned if there are no errors. +*/ +TInt RCoreImageReader::ImageError(int aItemsRead, int aExpected, char *aInfo) { + if (aItemsRead != aExpected) { + Print(EError, "Read From Core Image Failed (%s) \n", aInfo); + return KErrCorrupt; + } + if (iCoreImage.eof()) { + Print(EError, "Premature End of File Detected (%s)\n", aInfo); + return KErrEof; + } + return KErrNone; +} + +// ----------------------------------------------------------- +// CCoreImage +// ----------------------------------------------------------- + +/** +Initialises the reader to be used for accessing the core image file + +@param aReader Reader to be used for accessing the core image file +*/ +CCoreImage::CCoreImage(RCoreImageReader* aReader) : iReader(aReader), +iRootDirectory(0), iFileEntries(0), iDirTreeOffset(0), +iDirTreeSize(0), iDirFileEntriesOffset(0), +iDirFileEntriesSize(0), iImageSize(0) { +} + +/** +Deletes the directory tree that was created from the core image. +*/ +CCoreImage::~CCoreImage() { + if(iRootDirectory){ + iRootDirectory->Destroy() ; + iRootDirectory = 0 ; + } +} + + +/** +Creates the node to be used as the root directory of the directory tree. + +@return KErrNone for successful read or error number if failed +*/ +TInt CCoreImage::CreateRootDir() { + iRootDirectory = new TRomNode(""); + if (iRootDirectory == 0 ) + return KErrNoMemory; + return KErrNone; +} + +/** +Processes the core image file to produce a directory tree. + +@return KErrNone for successful read or error number if failed +*/ +TInt CCoreImage::ProcessImage() { + iRomFileName = iReader->Filename(); + int result = CreateRootDir(); + if (result == KErrNone) { + if (iReader->Open()) { + RCoreImageReader::TImageType imageType = iReader->ReadImageType(); + if (imageType == RCoreImageReader::E_ROFS) { + TRofsHeader header; + result = iReader->ReadCoreHeader(header); + if (result == KErrNone) { + SaveDirInfo(header); + result = ProcessDirectory(0); + } + } + else + result = KErrNotSupported; + } + else + result = KErrGeneral; + } + return result; +} + +/** +Processes the directory in the core image file. + +@param aAdjustment The difference between offsets in the core image directory and +@return KErrNone for successful read or error number if failed +*/ +TInt CCoreImage::ProcessDirectory(long aAdjustment) { + long filePos = iDirTreeOffset - aAdjustment; + TDirectoryEntry *firstDir = new TDirectoryEntry(filePos, iReader, iRootDirectory); + if (firstDir == 0) + return KErrNoMemory; + TInt result = firstDir->Process(aAdjustment); + delete firstDir; + return result; +} + +/** +Saves directory information from core image header for later usage. + +@param aHeader Header containing information to be saved +*/ +void CCoreImage::SaveDirInfo(TRofsHeader& aHeader) { + iDirTreeOffset = aHeader.iDirTreeOffset; + iDirTreeSize = aHeader.iDirTreeSize; + iDirFileEntriesOffset = aHeader.iDirFileEntriesOffset; + iDirFileEntriesSize = aHeader.iDirFileEntriesSize; + iImageSize = aHeader.iMaxImageSize; +} + +/** +Saves directory information from extension image header for later usage. + +@param aHeader Header containing information to be saved +*/ +void CCoreImage::SaveDirInfo(TExtensionRofsHeader& aHeader) { + iDirTreeOffset = aHeader.iDirTreeOffset; + iDirTreeSize = aHeader.iDirTreeSize; + iDirFileEntriesOffset = aHeader.iDirFileEntriesOffset; + iDirFileEntriesSize = aHeader.iDirFileEntriesSize; + iImageSize = aHeader.iMaxImageSize; +} + +/** +Displays the directory tree. This is used for debug purposes only. +*/ +void CCoreImage::Display(ostream* aOut) { + iRootDirectory->DisplayStructure(aOut); +} + +/** +Reads offset where directory tree starts in core image. + +@return offset of directory tree in image +*/ +long CCoreImage::DirTreeOffset() { + return iDirTreeOffset; +} + +TRomNode* CCoreImage::CopyDirectory(TRomNode*& aSourceDirectory) { + return iRootDirectory->CopyDirectory(aSourceDirectory); +} + +TRomNode* CCoreImage::RootDirectory() { + return iRootDirectory; +} + +void CCoreImage::SetRootDirectory(TRomNode* aDir) { + iRootDirectory = aDir; +} + +const char* CCoreImage::RomFileName() const { + return iRomFileName.c_str(); +} + +TInt CCoreImage::Size() const { + return iImageSize; +} + +// ----------------------------------------------------------- +// TDirectoryEntry +// ----------------------------------------------------------- + +/** +Initialises the directory entry + +@param aFilePos Position within file where the directory entry is located +@param aReader Handle used to access the file; +@param aDir The TRomNode associated with this directory +*/ +TDirectoryEntry::TDirectoryEntry(long filePos, RCoreImageReader* aReader, TRomNode* aDir) : +iReader(aReader), iCurrentDir(aDir),iFilePos(filePos), +iAdjustment(0) { +} + +/** +Empty destructor. +*/ +TDirectoryEntry::~TDirectoryEntry() { +} + +/** +Processes the current directory entry. If the directory has any files it will +create the appropriate file entries in the directory tree. If the directory +has any subdirectories it will create nodes in the directory tree and will +create an TDirectoryEntry and then use that to process the subdirectory + +@param aAdjustment The difference between offsets in the core image directory and +the actual position in the file +*/ +TInt TDirectoryEntry::Process(long aAdjustment) { + TRofsDir dir; + iAdjustment = aAdjustment; + long dirStartPos = iFilePos; + int result = KErrNone; + int dirSize = iReader->ReadDirEntry(dir, iFilePos); + if (dirSize != 0) { + if (dir.iFileBlockAddress != 0) { + // directory has files in it + result = AddFiles(dir.iFileBlockAddress-iAdjustment, dir.iFileBlockSize); + } + if (result == KErrNone && dir.iStructSize > dirSize) { + // directory has subdirectories + result = AddSubDirs(dirStartPos + dir.iStructSize); + } + } + else + result = KErrGeneral; + + return result; +} + +/** +Processes the subdirectories in the current directory. For each subdirectory +a TDirectoryEntry is created and is then used to process the directory + +@param aEndDirPos Position where the directory block finishes. This is to determine when all subdirectories have been processed +*/ +TInt TDirectoryEntry::AddSubDirs(long aEndDirPos) { + TRofsEntry entry; + iFilePos = iReader->FilePosition(); + TInt result = KErrNone; + string name ; + while (iFilePos < aEndDirPos && result == KErrNone) { + TInt size = iReader->ReadRofEntry(entry, iFilePos); + UTF16String uniName ; + if (size >0) { + TUint16* nameBuf = uniName.Alloc(entry.iNameLength); + *nameBuf = entry.iName[0]; + result = iReader->ReadRofEntryName(&nameBuf[1],entry.iNameLength - 1); + if(result != KErrNone){ + return result ; + } + if (uniName.ToUTF8(name)) { + TRomNode *dir = iCurrentDir->NewSubDir(name.c_str()); + TDirectoryEntry *subDir = new TDirectoryEntry( + entry.iFileAddress-iAdjustment, iReader, dir); + if (subDir != 0) { + // now process the subdirectory + subDir->Process(iAdjustment); + iFilePos += entry.iStructSize; + // round to nearest word boundary + iFilePos += (4-entry.iStructSize) & 3; + } + else + result = KErrNoMemory; + + if (subDir) { + delete subDir; + } + } + else + result = KErrNoMemory; + } + else { + result = KErrGeneral; + } + } + return result; +} + +/** +Processes a file entries block in the directory and creates the appropriate +nodes for each file in the block + +@param aStartPosition start for file block in the core image file +@param aSize size of the file entries block +*/ +TInt TDirectoryEntry::AddFiles(long aStartPosition, int aSize ) { + long savedPosition = iReader->FilePosition(); + long currentPos = aStartPosition; + iReader->SetFilePosition(aStartPosition); + long endPos = aStartPosition+aSize; + TRofsEntry entry; + TInt result = KErrNone; + string name ; + UTF16String uniName; + while (currentPos < endPos && result == KErrNone) { + TInt size = iReader->ReadRofEntry(entry, currentPos); + if (size > 0) { + TUint16* nameBuf = uniName.Alloc(entry.iNameLength); + *nameBuf = entry.iName[0] ; + result = iReader->ReadRofEntryName(&nameBuf[1],entry.iNameLength - 1); + if(result != KErrNone){ + return result ; + } + if (uniName.ToUTF8(name)) { + result = CreateFileEntry(name.c_str(), entry); + currentPos += entry.iStructSize; + } + else + result = KErrNoMemory; + } + else { + result = KErrGeneral; + } + } + iReader->SetFilePosition(savedPosition); + return result; +} + +/** +Creates a new node for a file entry and the associated TRomBuilderEntry. + +@param aNameStr Name of the file entry to be created +@param aFileAddress Address of file in the core image +@param aFileSize Size of the file +*/ +TInt TDirectoryEntry::CreateFileEntry(const char* aNameStr, TRofsEntry& aRofsEntry) { + TRomBuilderEntry *fileEntry = new TRomBuilderEntry(0,aNameStr); + if (fileEntry == 0) + return KErrNoMemory; + + memcpy(&fileEntry->iUids[0], &aRofsEntry.iUids[0], sizeof(fileEntry->iUids)); + fileEntry->iFileOffset = aRofsEntry.iFileAddress; + fileEntry->SetRealFileSize(aRofsEntry.iFileSize); + TRomNode *file = new TRomNode(aNameStr, fileEntry); + file->iSize = aRofsEntry.iFileSize; + if (file == 0) { + delete fileEntry; + return KErrNoMemory; + } + file->iAtt = aRofsEntry.iAtt; + file->iAttExtra = aRofsEntry.iAttExtra; + iCurrentDir->AddFile(file); + return KErrNone; +} +