imgtools/romtools/readimage/src/image_reader.cpp
changeset 0 044383f39525
child 590 360bd6b35136
--- /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;
+}