diff -r 820b22e13ff1 -r 39c28ec933dd imgtools/romtools/readimage/src/image_reader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/readimage/src/image_reader.cpp Mon May 10 19:54:49 2010 +0100 @@ -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 (iwidth(6); + out->fill('0'); + *out << i << ":"; + while (iwidth(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. + int r = CHDIR(cPtr); (void)r; + } + // repeat till cPtr is NULL. + while (cPtr!=NULL) + { + if ((cPtr = strtok(NULL,aDelimiter)) != NULL) + { + // create the directory. + MKDIR(cPtr); + // change current working directory. + int r = CHDIR(cPtr); (void)r; + } + } + // revert back the working directory. + int r = CHDIR(currWorkingDir); (void)r; + // 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; +}