imgtools/imglib/filesystem/source/dirregion.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Class receives tree structured directory and file information. And 
       
    16 * prepares the cluster versus content MAP by traversing through the same. 
       
    17 * Later all the prepared clusters are written into image file.
       
    18 * @internalComponent
       
    19 * @released
       
    20 *
       
    21 */
       
    22 
       
    23 
       
    24 #include "dirregion.h"
       
    25 
       
    26 /**
       
    27 Constructor:
       
    28 1.Get the instance of class CCluster
       
    29 2.Intializes the Cluster pointer
       
    30 3.Intialize the flags and other variables
       
    31 
       
    32 @internalComponent
       
    33 @released
       
    34 
       
    35 @param aNodeList - Root node placed in this list
       
    36 @param aFileSystemPtr - CFileSystem class pointer
       
    37 */
       
    38 CDirRegion::CDirRegion(EntryList aNodeList,
       
    39 					   CFileSystem * aFileSystemPtr):
       
    40 					   iCurrentDirEntry(false),
       
    41 					   iParentDirEntry(false),
       
    42 					   iFirstCluster(true),
       
    43    					   iNodeList(aNodeList)
       
    44 {
       
    45 	iClusterSize = aFileSystemPtr->GetClusterSize();
       
    46 	iRootDirSizeInBytes = (aFileSystemPtr->GetRootDirSectors () * 
       
    47 						   aFileSystemPtr->GetBytesPerSector());
       
    48 	int totalClusters = aFileSystemPtr->GetTotalCluster();
       
    49 	iClusterPtr = CCluster::Instance(iClusterSize,totalClusters);
       
    50 	if(iClusterPtr == NULL)
       
    51 	{
       
    52 		throw ErrorHandler(CLUSTERERROR,"Instance creation error", __FILE__, __LINE__);
       
    53 	}
       
    54 	iClusterSize = iClusterPtr->GetClusterSize();
       
    55 }
       
    56 
       
    57 /**
       
    58 Destructor: 
       
    59 1. Clean the Node List 
       
    60 2. Clean the instance of Cluster object 
       
    61 3. Clean the Cluster MAP.
       
    62 4. Invokes the DestroyShortEntryList to clear the contents of static GShortEntryList.
       
    63 
       
    64 @internalComponent
       
    65 @released
       
    66 */
       
    67 CDirRegion::~CDirRegion()
       
    68 {
       
    69 	if(iNodeList.size() > 0)
       
    70 	{
       
    71 		//Delete the root node
       
    72 		delete iNodeList.front();
       
    73 	}
       
    74 	if(iClusterPtr != NULL)
       
    75 	{
       
    76 		delete iClusterPtr;
       
    77 		iClusterPtr = NULL;
       
    78 	}
       
    79 	iClusterMap.clear();
       
    80 	ClongName::DestroyShortEntryList();
       
    81 }
       
    82 
       
    83 /**
       
    84 Function to return Clusters per entry map(input for FAT table generator function) 
       
    85 container
       
    86 
       
    87 @internalComponent
       
    88 @released
       
    89 
       
    90 @return - returns clusters per entry map container
       
    91 */
       
    92 TClustersPerEntryMap* CDirRegion::GetClustersPerEntryMap() const
       
    93 {
       
    94 	return iClusterPtr->GetClustersPerEntryMap();
       
    95 }
       
    96 
       
    97 /**
       
    98 Function responsible to write all the clusters available in iClusterMap
       
    99 into file. 
       
   100 
       
   101 @internalComponent
       
   102 @released
       
   103 
       
   104 @param aOutPutStream - output file stream to write clusters in it
       
   105 */
       
   106 void CDirRegion::WriteClustersIntoFile(OfStream& aOutPutStream)
       
   107 {
       
   108 	StringMap::iterator mapBeginIter = iClusterMap.begin();
       
   109 	StringMap::iterator mapEndIter= iClusterMap.end();
       
   110 	//MAPs are sorted associative containers, so no need to sort
       
   111 	String tempString;
       
   112 	while(mapBeginIter != mapEndIter)
       
   113 	{
       
   114 		tempString = (*mapBeginIter++).second;
       
   115 		aOutPutStream.write(tempString.c_str(),tempString.length());
       
   116 	}
       
   117 	aOutPutStream.flush();
       
   118 	if(aOutPutStream.bad())
       
   119 	{
       
   120 		throw ErrorHandler(FILEWRITEERROR, __FILE__, __LINE__);
       
   121 	}
       
   122 }
       
   123 
       
   124 
       
   125 /**
       
   126 Function takes the full entry name and formats it as per FAT spec requirement
       
   127 Requirement:
       
   128 1. All the names should be of 11 characters length.
       
   129 2. Name occupies 8 characters and the extension occupies 3 characters.
       
   130 3. If the name length is less than 8 characters, padd remaining characters with '0x20' 
       
   131 4. If the extension length is less than 3 characters, padd remaining characters with '0x20' 
       
   132 5. If the Name or extension exceeds from its actual length then it is treated as long name.
       
   133 
       
   134 @internalComponent
       
   135 @released
       
   136 
       
   137 @param aString - the String needs to be formatted
       
   138 @param aAttrValue - the entry attribute
       
   139 */
       
   140 void CDirRegion::FormatName(String& aString, char aAttrValue)
       
   141 {
       
   142 	if(!aString.empty())
       
   143 	{
       
   144 		if((*aString.begin()) != KDot)
       
   145 		{
       
   146 			//Get the file extension start index
       
   147 			int extensionStartIndex = aString.find_last_of (KDot);
       
   148 			if(aAttrValue != EAttrDirectory && extensionStartIndex != -1)
       
   149 			{
       
   150 				//Erase the dot, because it is not required to be written in the FAT image
       
   151 				aString.erase(extensionStartIndex,1);
       
   152 				//Apply Space padding for the Name
       
   153 				aString.insert (extensionStartIndex,(ENameLength - extensionStartIndex), KSpace);
       
   154 				int totalStringLength = aString.length();
       
   155 				//Apply Space padding for the  Extension
       
   156 				if(totalStringLength < ENameLengthWithExtension)
       
   157 				{
       
   158 					aString.insert(totalStringLength,(ENameLengthWithExtension - totalStringLength), KSpace);
       
   159 					return;
       
   160 				}
       
   161 			}
       
   162 			else
       
   163 			{
       
   164 				int nameEndIndex = aString.length();
       
   165 				//Apply Space padding for the directory Name
       
   166 				aString.insert(nameEndIndex,(ENameLengthWithExtension - nameEndIndex),KSpace);
       
   167 				return;
       
   168 			}
       
   169 		}
       
   170 		else
       
   171 		{	//Apply Space padding for either '.' or ".."
       
   172 			aString.append((ENameLengthWithExtension - aString.length()),KSpace);
       
   173 			return;
       
   174 		}
       
   175 	}
       
   176 	else
       
   177 	{
       
   178 		throw ErrorHandler(EMPTYFILENAME, __FILE__, __LINE__);
       
   179 	}
       
   180 }
       
   181 
       
   182 /**
       
   183 Function responsible to classify the entry name as long name or regular name.
       
   184 
       
   185 @internalComponent
       
   186 @released
       
   187 
       
   188 @param aEntry - the directory entry
       
   189 @return - returns true if it is long name else false.
       
   190 */
       
   191 bool CDirRegion::IsLongEntry(CDirectory* aEntry) const
       
   192 {
       
   193 	String entryName = aEntry->GetEntryName();
       
   194 	unsigned int receivedNameLength = entryName.length();
       
   195 	unsigned int firstDotLocation = entryName.find_first_of(KDot);
       
   196 	unsigned int lastDotLocation = entryName.find_last_of(KDot);
       
   197 
       
   198 	if(firstDotLocation == lastDotLocation)
       
   199 	{
       
   200 		if(aEntry->GetEntryAttribute() == EAttrDirectory)
       
   201 		{
       
   202 			// If the directory name length is more than 8 characters, then it is a long name
       
   203 			if(receivedNameLength > ENameLength)
       
   204 			{
       
   205 				return true;
       
   206 			}
       
   207 		}
       
   208 		else
       
   209 		{
       
   210 			int extensionIndex = lastDotLocation;
       
   211 			unsigned int fileExtensionLength = receivedNameLength - extensionIndex - 1;
       
   212 			/*Either the full name length is greater than 11 or the extension 
       
   213 			 *length is greater than 3, then it is considered as long name.
       
   214 			 */
       
   215 			if((receivedNameLength > ENameLengthWithExtension) 
       
   216 			   || (fileExtensionLength > EExtensionLength))
       
   217 			{
       
   218 				return true;
       
   219 			}
       
   220 		}
       
   221 		return false;
       
   222 	}
       
   223 	else
       
   224 	{
       
   225 		//If the name contains multiple dots, then it is a long name.
       
   226 		return true;	
       
   227 	}
       
   228 }
       
   229 
       
   230 /**
       
   231 Function responsible to 
       
   232 1. Invoke long name class
       
   233 2. Invoke the methods to create long and short entries
       
   234 3. Receive the string filled with long entries
       
   235 
       
   236 @internalComponent
       
   237 @released
       
   238 
       
   239 @param aEntry - the entry
       
   240 @param aDirString - long name entry appended to this string
       
   241 */
       
   242 
       
   243 void CDirRegion::CreateLongEntries(CDirectory* aEntry,String& aDirString)
       
   244 {
       
   245 	ClongName aLongNameObject(iClusterPtr,aEntry);
       
   246 	String tempString = aLongNameObject.CreateLongEntries();
       
   247 	if(tempString.length() == 0)
       
   248 	{
       
   249 		tempString.erase();
       
   250 		throw ErrorHandler(EMPTYFILENAME, __FILE__, __LINE__);
       
   251 	}
       
   252 	else
       
   253 	{
       
   254 		aDirString.append(tempString.c_str(),tempString.length());
       
   255 		tempString.erase();
       
   256 		WriteEntryToString(aLongNameObject.CreateShortEntry(aEntry),aDirString);
       
   257 	}
       
   258 }
       
   259 
       
   260 /**
       
   261 Function takes a single entry and writes its attributes into tempString.
       
   262 Later this string is appended with the string received in the argument
       
   263 
       
   264 @internalComponent
       
   265 @released
       
   266 
       
   267 @param aEntry - the entry which attributes are needs to be written into aString
       
   268 @param aString - entry attributes appended into this string
       
   269 */
       
   270 void CDirRegion::WriteEntryToString(CDirectory* aEntry,String& aString)
       
   271 {
       
   272 	String tempString;
       
   273 	String entryName = aEntry->GetEntryName();
       
   274 	tempString.append(ToUpper(entryName));
       
   275 	//appends the attributes only once
       
   276 	tempString.append(KWriteOnce, aEntry->GetEntryAttribute());
       
   277 	tempString.append(KWriteOnce, aEntry->GetNtReservedByte());
       
   278 	tempString.append(KWriteOnce, aEntry->GetCreationTimeMsecs());
       
   279 	unsigned short int createdTime = aEntry->GetCreatedTime();
       
   280 	tempString.append(ToString(createdTime));
       
   281 	unsigned short int creationDate = aEntry->GetCreationDate();
       
   282 	tempString.append(ToString(creationDate));
       
   283 	unsigned short int lastAccessDate = aEntry->GetLastAccessDate();
       
   284 	tempString.append(ToString(lastAccessDate));
       
   285 	unsigned short int clusterNumberHi = aEntry->GetClusterNumberHi();
       
   286 	tempString.append(ToString(clusterNumberHi));
       
   287 	unsigned short int lastWriteTime = aEntry->GetLastWriteTime();
       
   288 	tempString.append(ToString(lastWriteTime));
       
   289 	unsigned short int lastWriteDate = aEntry->GetLastWriteDate();
       
   290 	tempString.append(ToString(lastWriteDate));
       
   291 	unsigned short int clusterNumberLow = aEntry->GetClusterNumberLow();
       
   292 	tempString.append(ToString(clusterNumberLow));
       
   293 	unsigned int fileSize = aEntry->GetFileSize();
       
   294 	tempString.append(ToString(fileSize));
       
   295 
       
   296 	aString.append(tempString.c_str(),KDirectoryEntrySize);
       
   297 	tempString.erase();
       
   298 }
       
   299 
       
   300  
       
   301 
       
   302 /**
       
   303 Function responsible to 
       
   304 1. Read the file content and write into string.
       
   305 2. Invoke the function to push data clusters into cluster Map
       
   306 
       
   307 @internalComponent
       
   308 @released
       
   309 
       
   310 @param aEntry - the directory entry node
       
   311 */
       
   312 void CDirRegion::WriteFileDataInToCluster(CDirectory* aEntry)
       
   313 {
       
   314 	iInputStream.open(aEntry->GetFilePath().c_str(),Ios::binary);
       
   315 	if(iInputStream.fail() == true )
       
   316 	{
       
   317 		throw ErrorHandler(FILEOPENERROR,(char*)aEntry->GetFilePath().c_str(),__FILE__,__LINE__);
       
   318 	}
       
   319 	else
       
   320 	{
       
   321 		iInputStream.seekg (0,Ios::end);
       
   322 		Long64 fileSize = iInputStream.tellg(); 
       
   323 		iInputStream.seekg(0,Ios::beg);
       
   324 		char* dataBuffer = (char*)malloc((unsigned int)fileSize);
       
   325 		if(dataBuffer == 0)
       
   326 		{
       
   327 			throw ErrorHandler(MEMORYALLOCATIONERROR, __FILE__, __LINE__);
       
   328 		}
       
   329 		//Read the whole file in one short
       
   330 		iInputStream.read (dataBuffer,fileSize);
       
   331 		
       
   332 		Long64 bytesRead = (unsigned int)iInputStream.tellg();
       
   333 		if((iInputStream.bad()) || (bytesRead != fileSize))
       
   334 		{
       
   335 			throw ErrorHandler(FILEREADERROR,(char*)aEntry->GetFilePath().c_str(), __FILE__, __LINE__);
       
   336 		}
       
   337 		String clusterData(dataBuffer,(unsigned int)bytesRead);
       
   338 		PushStringIntoClusterMap(iClusterPtr->GetCurrentClusterNumber(),clusterData,iClusterSize,aEntry->GetEntryAttribute());
       
   339 	}
       
   340 	iInputStream.close();
       
   341 }
       
   342 
       
   343 
       
   344 /**
       
   345 Function invokes 
       
   346 1. CheckEntry function, to identify whether the received entry list is proper or not.
       
   347 2. Invokes CreateDirEntry, to create directory and data portion of FAT image.
       
   348 
       
   349 @internalComponent
       
   350 @released
       
   351   
       
   352 */
       
   353 void CDirRegion::Execute()
       
   354 {
       
   355 	CheckEntry(iNodeList);
       
   356 	CreateDirEntry(iNodeList.front(),KParentDirClusterNumber);
       
   357 }
       
   358 
       
   359 /**
       
   360 Function is to initialize the Parent directory entry with parent cluster number
       
   361 and appends all the attributes into the string (aString).
       
   362 
       
   363 @internalComponent
       
   364 @released
       
   365 
       
   366 @param aParDirClusterNumber - parent directory cluster number
       
   367 @param aString - parent directory entry attributes appended to this string
       
   368 */
       
   369 void CDirRegion::CreateAndWriteParentDirEntry(unsigned int aParDirClusterNumber,String& aString)
       
   370 {
       
   371 	const char* parentDirName = ".."; //Indicates parent directory entry name
       
   372 	CDirectory* parentDirectory = new CDirectory((char*)parentDirName);
       
   373 
       
   374 	parentDirectory->SetEntryAttribute(EAttrDirectory);
       
   375 	parentDirectory->SetClusterNumberLow((unsigned short) (aParDirClusterNumber & KHighWordMask));
       
   376 	parentDirectory->SetClusterNumberHi((unsigned short) (aParDirClusterNumber >> KBitShift16));
       
   377 
       
   378 	String tempString(parentDirectory->GetEntryName());
       
   379 	FormatName(tempString,EAttrDirectory);
       
   380 	parentDirectory->SetEntryName(tempString);
       
   381 	tempString.erase();
       
   382 	
       
   383 	WriteEntryToString(parentDirectory,aString);
       
   384 	iParentDirEntry = true;
       
   385 	delete parentDirectory;
       
   386 	parentDirectory = NULL;
       
   387 }
       
   388 
       
   389 /**
       
   390 Function responsible to 
       
   391 1. Initialize the Current directory entry attribute
       
   392 2. Write the entry attributes into received string
       
   393 
       
   394 @internalComponent
       
   395 @released
       
   396 
       
   397 @param aCurDirClusterNumber - Current directory Cluster number
       
   398 @param aString - the entry attributes should be appended to this string
       
   399 */
       
   400 void CDirRegion::CreateAndWriteCurrentDirEntry(unsigned int aCurClusterNumber,String& aString)
       
   401 {
       
   402 	const char* currentDirName = "."; //Indicates Current Directory entry name
       
   403 	iCurEntryClusterNumber = aCurClusterNumber;
       
   404 	CDirectory* currentDirectory = new CDirectory((char*)currentDirName);
       
   405 
       
   406 	currentDirectory->SetEntryAttribute(EAttrDirectory);
       
   407 	currentDirectory->SetClusterNumberLow((unsigned short) (iCurEntryClusterNumber & KHighWordMask));
       
   408 	currentDirectory->SetClusterNumberHi((unsigned short) (iCurEntryClusterNumber >> KBitShift16));
       
   409 
       
   410 	String tempString(currentDirectory->GetEntryName());
       
   411 	FormatName(tempString,EAttrDirectory);
       
   412 	currentDirectory->SetEntryName(tempString);
       
   413 	tempString.erase();
       
   414 
       
   415 	WriteEntryToString(currentDirectory,aString);
       
   416 	iCurrentDirEntry = true;
       
   417 	delete currentDirectory;
       
   418 	currentDirectory = NULL;
       
   419 }
       
   420 
       
   421 /**
       
   422 Function responsible to push the directory entry clusters into cluster MAP only if the
       
   423 directory entry string size is greater than the cluster size.
       
   424 
       
   425 @internalComponent
       
   426 @released
       
   427 
       
   428 @param aNumber - is the Cluster Key used to insert the cluster into cluster map
       
   429 @param aString - is the directory entry string
       
   430 @param aClustersRequired - No of clusters required to hold this string
       
   431 */
       
   432 
       
   433 void CDirRegion::PushDirectoryEntryString(unsigned int aNumber,String& aString,int aClustersRequired)
       
   434 {
       
   435 	int clusterCount = 0;
       
   436 	int clusterKey = aNumber;
       
   437 	iClusterPtr->CreateMap(aNumber,clusterKey);
       
   438 	iClusterMap[clusterKey] =	aString.substr(clusterCount*iClusterSize,iClusterSize);
       
   439 	++clusterCount;
       
   440 	String clusterSizeString;
       
   441 	for(; clusterCount < aClustersRequired; ++clusterCount)
       
   442 	{
       
   443 		clusterKey = iClusterPtr->GetCurrentClusterNumber();
       
   444 		clusterSizeString = aString.substr(clusterCount*iClusterSize,iClusterSize);
       
   445 		clusterSizeString.append((iClusterSize - clusterSizeString.length()),0);
       
   446 		iClusterMap[clusterKey] = clusterSizeString;
       
   447 		iClusterPtr->CreateMap(aNumber,clusterKey);
       
   448 		iClusterPtr->UpdateNextAvailableClusterNumber();
       
   449 	}
       
   450 }
       
   451 
       
   452 /**Function responsible to 
       
   453 1. Convert the string into equal size clusters of cluster size
       
   454 2. Insert the clusters into Cluster MAP
       
   455 
       
   456 @internalComponent
       
   457 @released
       
   458 
       
   459 @param aNumber - cluster number, used to map the cluster
       
   460 @param aString - reference of input string
       
   461 @param aClusterSize - used to split the string
       
   462 @param aAttribute - current entry attribute
       
   463 */
       
   464 void CDirRegion::PushStringIntoClusterMap(unsigned int aNumber, String& aString, unsigned long int aClusterSize,char aAttribute)
       
   465 {
       
   466 	int receivedStringLength = aString.length();
       
   467 	/* Precaution, once the map is initialized with specific cluster number don't over write
       
   468 	 * it once again. Look for the cluster number within the existing MAP and then proceed with 
       
   469 	 * filling in the cluster.
       
   470 	 */
       
   471 	StringMap::iterator iter= iClusterMap.find(aNumber);
       
   472 	if(iter == iClusterMap.end())
       
   473 	{
       
   474 		/* The length of the cluster content (aString) can be more or less than the cluster size, 
       
   475 		 * hence, calculate the total number of clusters required.
       
   476 		 */
       
   477 		int clustersRequired = receivedStringLength / aClusterSize;
       
   478 		if((receivedStringLength % aClusterSize) > 0)
       
   479 		{
       
   480 			++clustersRequired;
       
   481 		}
       
   482 		if((clustersRequired > 1) && (aAttribute == EAttrDirectory))
       
   483 		{
       
   484 			PushDirectoryEntryString(aNumber,aString,clustersRequired);
       
   485 			return;
       
   486 		}
       
   487 		int updatedClusterNumber = aNumber;
       
   488 		String clusterSizeString;
       
   489 		for(short int clusterCount = 0; clusterCount < clustersRequired; ++clusterCount)
       
   490 		{
       
   491 			/* In case of the contents occupying more than one cluster, break the contents into
       
   492 			 * multiple parts, each one measuring as that of the cluster size.
       
   493 			 */
       
   494 			clusterSizeString = aString.substr(clusterCount * aClusterSize,aClusterSize);
       
   495 			iClusterPtr->CreateMap(aNumber,updatedClusterNumber);
       
   496 			if(clusterSizeString.length() < aClusterSize)
       
   497 			{
       
   498 				/* Copied string size is less than cluster size, fill the remaining space
       
   499 				 * with zero
       
   500 				 */
       
   501 				clusterSizeString.append((aClusterSize - clusterSizeString.length()),0);
       
   502 			}
       
   503 			// Insert the String into ClusterMap	
       
   504 			iClusterMap[updatedClusterNumber] = clusterSizeString;
       
   505 		
       
   506 			iClusterPtr->UpdateNextAvailableClusterNumber();
       
   507 			updatedClusterNumber = iClusterPtr->GetCurrentClusterNumber ();
       
   508 		}
       
   509 		/* In the above loop, cluster number is incremented to point to the next entry.
       
   510 		 * However, before writing a directory or a volume id entry, it is always ensured 
       
   511 		 * to get the next cluster number. Hence in this case, it is required to decrement
       
   512 		 * the cluster number, so that the pointer points to the end of the cluster occupied.
       
   513 		 */
       
   514 		if(aAttribute == EAttrDirectory || aAttribute == EAttrVolumeId)
       
   515 		{
       
   516 			iClusterPtr->DecrementCurrentClusterNumber ();
       
   517 		}
       
   518 	}
       
   519 }
       
   520 
       
   521 /**
       
   522 Function is responsible to take in the tree structured directory 
       
   523 information and to initialize the starting cluster in the Cluster Map.
       
   524 
       
   525 @internalComponent
       
   526 @released
       
   527 
       
   528 @param aNodeList - the list which holds root entry
       
   529 */
       
   530 void CDirRegion::CheckEntry(EntryList aNodeList)
       
   531 {
       
   532 	if(aNodeList.size() > 0)
       
   533 	{
       
   534 		if(iRootDirSizeInBytes > 0)
       
   535 		{
       
   536 			//FAT16 Root entries are written into Cluster 1
       
   537 			iClusterKey = KFat16RootEntryNumber;
       
   538 		}
       
   539 		else
       
   540 		{
       
   541 			//FAT32 Root entries are written into Cluster 2			
       
   542 			iClusterPtr->UpdateNextAvailableClusterNumber();
       
   543 			iClusterKey = KFat32RootEntryNumber; 
       
   544 		}
       
   545 		if(aNodeList.front()->GetEntryList()->size() <= 0)
       
   546 		{
       
   547 			throw ErrorHandler(NOENTRIESFOUND, __FILE__, __LINE__);
       
   548 		}
       
   549 	}
       
   550 	else
       
   551 	{
       
   552 		throw ErrorHandler(ROOTNOTFOUND, __FILE__, __LINE__);
       
   553 	}
       
   554 }
       
   555 
       
   556 /**
       
   557 Function receives Tree structured folder information and does the following:
       
   558 1. Generates Directory Entry portion of FAT image recursively.
       
   559 2. If it finds the entry as file then writes its contents.
       
   560 3. If the entry is long name then longfilename class invoked to create long entries.
       
   561 
       
   562 @internalComponent
       
   563 @released
       
   564 
       
   565 @param aEntry  - Subdirectory pointer of root directory
       
   566 @param aParentDirClusterNumber - parent directory cluster number
       
   567 */
       
   568 void CDirRegion::CreateDirEntry(CDirectory* aEntry,unsigned int aParentDirClusterNumber)
       
   569 {
       
   570 	unsigned int currentDirClusterNumber = 0;
       
   571 	int rootClusterSize = 0;
       
   572 	if(iFirstCluster == true)
       
   573 	{
       
   574 			iCurrentDirEntry = true;
       
   575 			iParentDirEntry = true;
       
   576 			/**Root directory and Normal directory has one difference.
       
   577 			FAT16 : Root cluster occupies 32 sectors
       
   578 			FAT32 : Root cluster occupies only one cluster
       
   579 			*/
       
   580 			rootClusterSize = (iRootDirSizeInBytes > 0)?iRootDirSizeInBytes:iClusterSize; 
       
   581 	}
       
   582 	else
       
   583 	{
       
   584 		currentDirClusterNumber = Get32BitClusterNumber(aEntry->GetClusterNumberHi(),
       
   585 														aEntry->GetClusterNumberLow());
       
   586 	}
       
   587 	
       
   588 	//printIterator used while printing the entries
       
   589 	EntryList::iterator printIterator = aEntry->GetEntryList()->begin(); 
       
   590 	//traverseIterator used during recursive call
       
   591 	EntryList::iterator traverseIterator = printIterator;
       
   592 	
       
   593 	unsigned int dirEntryCount = aEntry->GetEntryList()->size();
       
   594 
       
   595 	String dirString;
       
   596 	String nameString;
       
   597 	CDirectory* tempDirEntry = (*printIterator);
       
   598 	//Writes all the Directory entries available in one Directory entry
       
   599 	while(dirEntryCount > 0)
       
   600 	{
       
   601 		tempDirEntry = (*printIterator);
       
   602 		
       
   603 		tempDirEntry->SetClusterNumberHi(iClusterPtr->GetHighWordClusterNumber());
       
   604 		tempDirEntry->SetClusterNumberLow(iClusterPtr->GetLowWordClusterNumber());
       
   605 
       
   606 		/* Every directory should have current and parent directory entries in its
       
   607 		 * respective cluster. Hence Create the current and parent directory entries 
       
   608 		 * only if it is not created already.
       
   609 		 */
       
   610 		if(!iCurrentDirEntry && !iParentDirEntry)
       
   611 		{
       
   612 			CreateAndWriteCurrentDirEntry(currentDirClusterNumber,dirString);
       
   613 			iClusterKey = currentDirClusterNumber;
       
   614 			CreateAndWriteParentDirEntry(aParentDirClusterNumber,dirString);
       
   615 		}
       
   616 		MessageHandler::ReportMessage(INFORMATION,
       
   617 									  ENTRYCREATEMSG,
       
   618 									  (char*)tempDirEntry->GetEntryName().c_str());
       
   619 		if(!IsLongEntry(tempDirEntry))
       
   620 		{
       
   621 			nameString.assign(tempDirEntry->GetEntryName());
       
   622 			FormatName(nameString,tempDirEntry->GetEntryAttribute());
       
   623 			tempDirEntry->SetEntryName(nameString);
       
   624 			nameString.erase();
       
   625 			WriteEntryToString(tempDirEntry,dirString);
       
   626 		}
       
   627 		else
       
   628 		{
       
   629 			CreateLongEntries(tempDirEntry,dirString);
       
   630 		}
       
   631 		if(tempDirEntry->IsFile())
       
   632 		{
       
   633 			WriteFileDataInToCluster(tempDirEntry);
       
   634 		}
       
   635 		else
       
   636 		{
       
   637 			iClusterPtr->UpdateNextAvailableClusterNumber ();
       
   638 		}
       
   639 		++printIterator;
       
   640 		--dirEntryCount;
       
   641 	}
       
   642 
       
   643 	iCurrentDirEntry = false;
       
   644 	iParentDirEntry = false;
       
   645 	aParentDirClusterNumber = currentDirClusterNumber;
       
   646 	if(iFirstCluster == true)
       
   647 	{
       
   648 		PushStringIntoClusterMap(iClusterKey,dirString,rootClusterSize,aEntry->GetEntryAttribute());
       
   649 		iFirstCluster = false;
       
   650 	}
       
   651 	else
       
   652 	{
       
   653 		PushStringIntoClusterMap(iClusterKey,dirString,iClusterSize,aEntry->GetEntryAttribute());
       
   654 	}
       
   655 
       
   656 	dirEntryCount = aEntry->GetEntryList()->size();
       
   657 
       
   658 	//Recursive algorithm to print all entries
       
   659 	while(dirEntryCount > 0)
       
   660 	{
       
   661 		if(aEntry->GetEntryList()->size() > 0)
       
   662 		{		
       
   663 			CreateDirEntry((*traverseIterator),aParentDirClusterNumber);
       
   664 		}
       
   665 		--dirEntryCount;
       
   666 		//if no entries found don't go deep
       
   667 		if(dirEntryCount > 0)
       
   668 		{
       
   669 			aEntry = (*++traverseIterator);
       
   670 		}
       
   671 	}
       
   672 }
       
   673 
       
   674 /**
       
   675 Function responsible to convert two 16 bit words into single 32 bit integer
       
   676 
       
   677 @internalComponent
       
   678 @released
       
   679 
       
   680 @param aHighWord - 16 bit high word
       
   681 @param aLowWord - 16 bit low word
       
   682 @return returns the 32 bit integer
       
   683 */
       
   684 unsigned int CDirRegion::Get32BitClusterNumber(unsigned int aHighWord, unsigned int aLowWord)
       
   685 {
       
   686 	unsigned int clusterNumber = aHighWord;
       
   687 	clusterNumber <<= KBitShift16;
       
   688 	clusterNumber |= aLowWord;
       
   689 	return clusterNumber;
       
   690 }