--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/readimage/src/image_reader.cpp Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,504 @@
+/*
+* 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 "image_reader.h"
+
+ImageReader::ImageReader(const char* aFile) : iDisplayOptions(0),iImgFileName(aFile)
+{
+}
+
+ImageReader::~ImageReader()
+{
+}
+
+void ImageReader::SetDisplayOptions(TUint32 aFlag)
+{
+ iDisplayOptions |= aFlag;
+}
+
+bool ImageReader::DisplayOptions(TUint32 aFlag)
+{
+ return ((iDisplayOptions & aFlag) != 0);
+}
+
+void ImageReader::DumpData(TUint* aData, TUint aLength)
+{
+ TUint *p=aData;
+ TUint i=0;
+ char line[256];
+ char *cp=(char*)aData;
+ TUint j=0;
+ memset(line,' ',sizeof(line));
+ while (i<aLength)
+ {
+ TUint ccount=0;
+ char* linep=&line[8*5+2];
+ *out<< "0x";
+ out->width(6);
+ out->fill('0');
+ *out << i << ":";
+ while (i<aLength && ccount<4)
+ {
+ *out<< " ";
+ out->width(8);
+ out->fill('0');
+ *out << *p++;
+ i+=4;
+ ccount++;
+ for (j=0; j<4; j++)
+ {
+ char c=*cp++;
+ if (c<32)
+ {
+ c = '.';
+ }
+ *linep++ = c;
+ }
+ }
+ *linep = '\0';
+ *out << line+(ccount*5) << endl;
+ }
+ }
+
+
+
+/**
+Function to extract specified file from a given image.
+
+@internalComponent
+@released
+
+@param aOffset - starting offset of the file in the image.
+@param aSize - size of the file in the image.
+@param aFileName - name of the file.
+@param aPath - full path of the file inside image.
+@param aFilePath - path where file has to be extracted.
+*/
+void ImageReader::ExtractFile(TUint aOffset,TInt aSize,const char* aFileName,const char* aPath,char* aFilePath,char* aData)
+{
+ // concatenate path where specified file needs to be extracted with
+ // path where file is located in the image.
+ string fullPath( aFilePath );
+ string delimiter( "\\" );
+ string appStr( "\\\\" );
+ fullPath.append( aPath );
+
+ // replace all the occurrence of slash with double slash.
+ FindAndInsertString( fullPath, delimiter, delimiter );
+ // now terminate the string with double slash.
+ fullPath.append( appStr );
+
+ // create specified directory where file needs to be extracted.
+ CreateSpecifiedDir( &fullPath[0], appStr.c_str() );
+
+ // concatenate path information with the filename
+ fullPath.append( aFileName );
+
+ // create an output stream to extract the specified file.
+ ofstream outfile (fullPath.c_str(), ios::out | ios::binary);
+ // create an input stream by opening the specified image file.
+ ifstream infile(ImageReader::iImgFileName.c_str(),ios::in|ios::binary);
+
+ //declare a buffer to store the data.
+ char* buffer = new char[aSize];
+
+ if(aData != NULL)
+ {
+ memcpy(buffer, aData + aOffset, aSize);
+ }
+ else if(infile.is_open())
+ {
+ // place the get pointer for the current input stream to offset bytes away from origin.
+ infile.seekg(aOffset,ios::beg);
+ //read number of bytes specified by the variable size
+ //from the stream and place it on to buffer.
+ infile.read(buffer,aSize);
+ //close the input stream after reading.
+ infile.close();
+ }
+ else
+ {
+ throw ImageReaderException(ImageReader::iImgFileName.c_str(), "Failed to open the image file");
+ }
+
+ if(outfile.is_open())
+ {
+ //writes number of bytes specified by the variable size
+ //from buffer to the current output stream.
+ outfile.write(buffer,aSize);
+ //close the output stream after writing.
+ outfile.close();
+ }
+ else
+ {
+ throw ImageReaderException(aFileName, "Failed to extract the file");
+ }
+
+ //delete the buffer.
+ delete[] buffer;
+}
+
+/**
+Function to create a given directory.
+
+@internalComponent
+@released
+
+@param aSrcPath - path of the directory that needs to be created.
+@param aDelimiter - delimiter.
+*/
+void ImageReader::CreateSpecifiedDir(char* aSrcPath,const char* aDelimiter)
+{
+ char* currWorkingDir = new char[_MAX_BUFFER_SIZE_];
+ string origPath;
+
+ origPath.assign(aSrcPath);
+
+
+ // get the current working directory and store in buffer.
+ if( _getcwd(currWorkingDir,_MAX_BUFFER_SIZE_) == NULL )
+ {
+ // throw an exception if unable to get current working directory information.
+ throw ImageReaderException((char*)ImageReader::iImgFileName.c_str(), "Failed to get the current working directory");
+ }
+ else
+ {
+ char* cPtr = strtok(aSrcPath,aDelimiter);
+
+ // check whether cPtr is a drive or a directory.
+ if(IsDrive(cPtr))
+ {
+ // if yes, then change the directory to cPtr.
+ string changeToDrive ;
+ changeToDrive.assign(cPtr);
+ changeToDrive.append(aDelimiter);
+
+ // change the current working directory to the specified directory.
+ if( _chdir(changeToDrive.c_str()) )
+ {
+ // throw an exception if unable to change the directory specified.
+ throw ImageReaderException((char*)ImageReader::iImgFileName.c_str(), "Failed to change to the directory specified");
+ }
+ }
+ else
+ {
+ // if not,then create a cPtr directory.
+ _mkdir(cPtr);
+ // change the current working directory to cPtr.
+ _chdir(cPtr);
+ }
+ // repeat till cPtr is NULL.
+ while (cPtr!=NULL)
+ {
+ if (cPtr = strtok(NULL,aDelimiter))
+ {
+ // create the directory.
+ _mkdir(cPtr);
+ // change current working directory.
+ _chdir(cPtr);
+ }
+ }
+ // revert back the working directory.
+ _chdir(currWorkingDir);
+ // replace the source path with the original path information.
+ strcpy(aSrcPath,origPath.c_str());
+ delete[] currWorkingDir;
+ }
+}
+
+
+/**
+Function to check whether the given string is a drive or a folder.
+
+@internalComponent
+@released
+
+@param aStr - string to be checked.
+@return - returns True if the given string is a drive else returns false.
+*/
+TBool ImageReader::IsDrive(char* aStr)
+{
+ TInt strlength = strlen(aStr);
+ //check for the last character in a given string,
+ //if the last character is colon then return true else false.
+ if(!strcmp(&aStr[strlength - 1],":"))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+/**
+Function to insert a given string with a delimiter.
+
+@internalComponent
+@released
+
+@param aSrcStr - string to be modified.
+@param aDelimiter - string to be checked.
+@param aAppStr - string to be inserted with the delimiter.
+*/
+void ImageReader::FindAndInsertString(string& aSrcStr,string& aDelimiter,string& aAppStr)
+{
+ string::size_type loc = 0;
+ string::size_type pos =0;
+ while(( pos = aSrcStr.find( aDelimiter, loc ) ) != ( string::npos ) )
+ {
+ if( pos != string::npos )
+ {
+ aSrcStr.insert(pos,aAppStr);
+ loc = pos + aAppStr.length() + 1;
+ }
+ }
+}
+
+/**
+Function to replace a delimiter with a given string.
+
+@internalComponent
+@released
+
+@param aSrcStr - string to be modified.
+@param aDelimiter - string to be checked.
+@param aReplStr - string to be replaced with the delimiter.
+*/
+void ImageReader::FindAndReplaceString( string& aSrcStr, string& aDelimiter, string& aReplStr )
+{
+ string::size_type loc = 0;
+ string::size_type pos =0;
+ while(( pos = aSrcStr.find( aDelimiter,loc) ) != ( string::npos ) )
+ {
+ if( pos != string::npos )
+ {
+ aSrcStr.replace( pos, aReplStr.length(),aReplStr );
+ loc = pos + aReplStr.length() + 1;
+ }
+ }
+}
+
+/**
+Function to extract individual or a subset of file.
+
+@internalComponent
+@released
+
+@param aData - ROM/ROFS image buffer pointer.
+*/
+void ImageReader::ExtractFileSet(char* aData)
+{
+ FILEINFOMAP fileInfoMap;
+ string dirSep(DIR_SEPARATOR), backSlash("\\"), Pattern;
+ TUint extfileCount = 0, noWcardFlag = 0, pos;
+
+ //Get the filelist map
+ GetFileInfo(fileInfoMap);
+
+ //Check for wildcards
+ pos = iPattern.rfind("\\");
+ if(pos == string::npos)
+ {
+ pos = iPattern.rfind("/");
+ if(pos == string::npos)
+ pos = 0;
+ }
+ pos = iPattern.find_first_of("*?", pos);
+ if(pos == string::npos)
+ {
+ noWcardFlag = 1;
+ }
+
+ //Process the map
+ if(fileInfoMap.size() > 0)
+ {
+ FILEINFOMAP::iterator begin = fileInfoMap.begin();
+ FILEINFOMAP::iterator end = fileInfoMap.end();
+
+ // Replace all backslashes with forward slashes
+ Pattern = iPattern;
+ FindAndReplaceString(Pattern, backSlash, dirSep);
+
+ // Insert root directory at the beginning if it is not there
+ pos = Pattern.find_first_not_of(" ", 0);
+ if(pos != string::npos)
+ {
+ if(Pattern.at(pos) != *DIR_SEPARATOR)
+ Pattern.insert(pos, dirSep);
+ }
+
+ // Assign CWD for destination path if it is empty
+ if(ImageReader::iZdrivePath.empty())
+ ImageReader::iZdrivePath.assign(".");
+
+ while(begin != end)
+ {
+ int status = 0;
+ PFILEINFO pInfo = 0;
+ string fileName = (*begin).first;
+ pInfo = (*begin).second;
+
+ // First match
+ status = FileNameMatch(Pattern, fileName, (iDisplayOptions & RECURSIVE_FLAG));
+
+ // If no match
+ if((!status) && noWcardFlag)
+ {
+ string newPattern(Pattern);
+
+ // Add * at the end
+ if(newPattern.at(Pattern.length()-1) != *DIR_SEPARATOR)
+ {
+ newPattern.append(DIR_SEPARATOR);
+ }
+ newPattern += "*";
+ status = FileNameMatch(newPattern, fileName, (iDisplayOptions & RECURSIVE_FLAG));
+
+ // If it matches update the pattern and reset wildcard flag
+ if(status)
+ {
+ Pattern = newPattern;
+ noWcardFlag = 0;
+ }
+ }
+
+ if(status)
+ {
+ // Extract the file
+
+ // Separarate the path and file name
+ string fullPath = fileName.substr(0, fileName.rfind(DIR_SEPARATOR));
+ string file = fileName.substr(fileName.rfind(DIR_SEPARATOR)+1, fileName.length());
+ FindAndReplaceString(fullPath, dirSep, backSlash);
+
+ // Extract only those files exists in the image
+ if(pInfo->iSize && pInfo->iOffset)
+ {
+ ExtractFile(pInfo->iOffset, pInfo->iSize, file.c_str(), fullPath.c_str() ,
+ &ImageReader::iZdrivePath[0], aData);
+
+ extfileCount++;
+ }
+ }
+
+ if(pInfo)
+ delete pInfo;
+ ++begin;
+ }
+ fileInfoMap.clear();
+ }
+
+ // Throw error if the extracted file count is zero
+ if(!extfileCount)
+ {
+ throw ImageReaderException((char*)ImageReader::iImgFileName.c_str(), "No matching files found for the given pattern");
+ }
+}
+
+/**
+To match the given file name aganist the given pattern with wildcards
+
+@internalComponent
+@released
+
+@param aPattern - input filename pattern.
+@param aFileName - input file name.
+@param aRecursiveFlag - recursive search flag.
+*/
+int ImageReader::FileNameMatch(string aPattern, string aFileName, int aRecursiveFlag)
+{
+ const char *InputString = aFileName.c_str();
+ const char *Pattern = aPattern.c_str();
+ const char *CurrPattern = 0, *CurrString = 0;
+
+ // If the input is empty then return false
+ if((aPattern.empty()) || (!InputString))
+ return 0;
+
+ // First candidate match
+ // Step 1: Look for the exact matches between the input pattern and the given file-name till
+ // the first occurrence of wildcard character (*). This should also skip a character
+ // from matching for the occurrence of wildcard character(?) in the pattern.
+ while ((*InputString) && (*Pattern != '*'))
+ {
+ if ((toupper(*Pattern) != toupper(*InputString)) && (*Pattern != '?'))
+ {
+ return 0;
+ }
+ Pattern++;
+ InputString++;
+ }
+
+ // Wildcard match
+ // Step 2: Now the input string (file-name) should be checked against the wildcard characters (* and ?).
+ // Skip the input string if the pattern points to wildcard character(*). Do the exact match for
+ // other characters in the patterns except the wildcard character(?). The path-separator should be
+ // considered as non-match for non-recursive option.
+ while (*InputString)
+ {
+ if ((*Pattern == '*'))
+ {
+ if (!*++Pattern)
+ {
+ // If recursive flag is set then this case matches for any character of the input string
+ // from the current position
+ if(aRecursiveFlag)
+ return 1;
+ }
+
+ // Update the current pattern and the current inputstring
+ CurrPattern = Pattern;
+ CurrString = InputString+1;
+ }
+ else if ((toupper(*Pattern) == toupper(*InputString)) || (*Pattern == '?'))
+ {
+ // Exact match for the path separator
+ // So recursively call the function to look for the exact path level match
+ if(*Pattern == '/')
+ return FileNameMatch(Pattern, InputString, aRecursiveFlag);
+
+ // Exact match so increment both
+ Pattern++;
+ InputString++;
+ }
+ else if ((*InputString == *DIR_SEPARATOR) && (!aRecursiveFlag))
+ {
+ // Inputstring points to path separator and it is not expected here for non-recursive case
+ return 0;
+ }
+ else
+ {
+ // Default case where it matches for the wildcard character *
+ Pattern = CurrPattern;
+ InputString = CurrString++;
+ }
+ }
+
+ // Leave any more stars in the pattern
+ while (*Pattern == '*')
+ {
+ Pattern++;
+ }
+
+ // Return the status
+ return !*Pattern;
+}