imgtools/romtools/rofsbuild/fatimagegenerator.cpp
changeset 607 378360dbbdba
parent 605 122d2b873fd1
child 626 ac03b93ca9c4
equal deleted inserted replaced
591:22486c9c7b15 607:378360dbbdba
       
     1 /*
       
     2 * Copyright (c) 2010 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 *
       
    16 */ 
       
    17 #include "fatimagegenerator.h"
       
    18 #include "fatcluster.h"
       
    19 #include "fsnode.h"
       
    20 #include "h_utl.h"
       
    21 
       
    22 #include <memory.h>
       
    23 #include <time.h>
       
    24 #include <iostream>
       
    25 #include <fstream>
       
    26 #include <iomanip>
       
    27 using namespace std;
       
    28 
       
    29 const TInt KCharsOfCmdWndLine = 80 ;
       
    30 const TInt KRootEntryCount = 0x200;
       
    31 const TInt KRootClusterIndex = 0;
       
    32 
       
    33 TFatImgGenerator::TFatImgGenerator(TSupportedFatType aType ,ConfigurableFatAttributes& aAttr ) :
       
    34 iType(aType),
       
    35 iFatTable(0),
       
    36 iFatTableBytes(0), 
       
    37 iTotalClusters(0),	
       
    38 iBytsPerClus(0)
       
    39 {
       
    40 	memset(&iBootSector,0,sizeof(iBootSector));
       
    41 	memset(&iFat32Ext,0,sizeof(iFat32Ext));
       
    42 	memset(&iFatHeader,0,sizeof(iFatHeader));
       
    43 	if(aAttr.iDriveSectorSize != 512 && aAttr.iDriveSectorSize != 1024 && aAttr.iDriveSectorSize != 2048 && aAttr.iDriveSectorSize != 4096) {
       
    44 		iType = EFatUnknown ;
       
    45 		return ;
       
    46 	}
       
    47 	*((TUint32*)iBootSector.BS_jmpBoot) = 0x00905AEB ; 
       
    48 	memcpy(iBootSector.BS_OEMName,"SYMBIAN ",8);
       
    49 	*((TUint16 *)iBootSector.BPB_BytsPerSec) = aAttr.iDriveSectorSize;
       
    50 	
       
    51 	iBootSector.BPB_NumFATs = aAttr.iDriveNoOfFATs;
       
    52 	iBootSector.BPB_Media = 0xF8 ;
       
    53 	iFatHeader.BS_DrvNum = 0x80 ;
       
    54 	iFatHeader.BS_BootSig = 0x29 ;
       
    55 
       
    56 	time_t rawtime;
       
    57 	time(&rawtime);
       
    58 	*((TUint32*)iFatHeader.BS_VolID) = (TUint32)rawtime;
       
    59 	memcpy(iFatHeader.BS_VolLab,aAttr.iDriveVolumeLabel,sizeof(iFatHeader.BS_VolLab));
       
    60 	if(aAttr.iImageSize == 0){
       
    61 		if(aType == EFat32)
       
    62 			aAttr.iImageSize = 0x100000000LL ;// 4G
       
    63 		else
       
    64 			aAttr.iImageSize = 0x40000000LL ; // 1G 
       
    65 	}
       
    66 
       
    67 	TUint32 totalSectors = (TUint32)((aAttr.iImageSize + aAttr.iDriveSectorSize - 1) / aAttr.iDriveSectorSize);
       
    68 	if(aType == EFat32) {
       
    69 		InitAsFat32(totalSectors,aAttr.iSectorPerCluster ,aAttr.iDriveSectorSize);
       
    70 	}
       
    71 	else if(aType == EFat16) {
       
    72 		InitAsFat16(totalSectors,aAttr.iSectorPerCluster,aAttr.iDriveSectorSize); 
       
    73 	}
       
    74 	if(iType == EFatUnknown) return ;
       
    75 	iBytsPerClus = iBootSector.BPB_SecPerClus * aAttr.iDriveSectorSize;
       
    76 //	if(iBytsPerClus > KMaxClusterBytes){
       
    77 //		Print(EError,"Cluster too large!\n");
       
    78 //		iType = EFatUnknown;
       
    79 //		return ;
       
    80 //	}
       
    81 	
       
    82 
       
    83 }
       
    84 TFatImgGenerator::~TFatImgGenerator() {
       
    85 	if(iFatTable)
       
    86 		delete []iFatTable;  
       
    87 	Interator it = iDataClusters.begin();
       
    88 	while(it != iDataClusters.end()){
       
    89 		TFatCluster* cluster = *it ;
       
    90 		delete cluster;
       
    91 		it++;
       
    92 	}
       
    93 }
       
    94 
       
    95 void TFatImgGenerator::InitAsFat16(TUint32 aTotalSectors,TUint8 aSecPerClus,TUint16 aBytsPerSec){
       
    96 	
       
    97 	TUint32 numOfClusters ;
       
    98 	if(aSecPerClus == 0) {
       
    99 		//Auto-calc the SecPerClus
       
   100 		// FAT32 ,Count of clusters must >= 4085 and < 65525 , however , to avoid the "off by xx" warning, 
       
   101 		// proprositional value >= (4085 + 16) && < (65525 - 16)
       
   102 		if(aTotalSectors < (4085 + 16)) { //when SecPerClus is 1, numOfClusters eq to aTotalSectors
       
   103 			iType = EFatUnknown ;
       
   104 			Print(EError,"Size is too small for FAT16, please set a bigger size !\n");
       
   105 			return ;
       
   106 		}
       
   107 		TUint8 secPerClusMax = KMaxClusterBytes / aBytsPerSec; 
       
   108 		numOfClusters = (aTotalSectors + secPerClusMax - 1) / secPerClusMax ; 
       
   109 		if(numOfClusters >= (65525 - 16)) { // too big 
       
   110 			iType = EFatUnknown ;
       
   111 			Print(EError,"Size is too big for FAT16, please use the FAT32 format!\n");
       
   112 			return ;
       
   113 		}
       
   114 		
       
   115 		aSecPerClus = 1;
       
   116 		while(aSecPerClus < secPerClusMax){
       
   117 			numOfClusters = (aTotalSectors + aSecPerClus - 1) / aSecPerClus ;
       
   118 			if (numOfClusters >= (4085 + 16) && numOfClusters < (65525 - 16)) {
       
   119 				break;
       
   120 			}
       
   121 			aSecPerClus <<= 1 ; 
       
   122 		}	
       
   123 	}
       
   124 	else {
       
   125 		if( (aSecPerClus * aBytsPerSec) > KMaxClusterBytes){
       
   126 			Print(EError,"Cluster too large!\n");
       
   127 			iType = EFatUnknown;
       
   128 			return ;
       
   129 		}
       
   130 		numOfClusters = (aTotalSectors + aSecPerClus - 1) / aSecPerClus;
       
   131 		if(numOfClusters >= (65525 - 16)){
       
   132       Print(EError,"Cluster count is too big for FAT16, please use the FAT32 format or set a new bigger sector count of cluster!\n");
       
   133 			iType = EFatUnknown ;
       
   134 			return ;
       
   135 		}
       
   136 		else if(numOfClusters < (4085 + 16)){
       
   137       Print(EError,"Cluster count is too small for FAT16, please set a new small sector count of cluster or set the size bigger!\n");
       
   138 			iType = EFatUnknown ;
       
   139 			return ;
       
   140 		}
       
   141 
       
   142 	}
       
   143 	iTotalClusters = (aTotalSectors + aSecPerClus - 1) / aSecPerClus ;
       
   144 	iFatTableBytes = ((iTotalClusters << 1) +  aBytsPerSec - 1) & (~(aBytsPerSec - 1)); 
       
   145 	iFatTable = new(std::nothrow) char[iFatTableBytes];
       
   146 	if(!iFatTable) {
       
   147         Print(EError,"Memory allocation failed for FAT16 Table!\n");
       
   148 		iType = EFatUnknown ;
       
   149 		return ;
       
   150 	}
       
   151 	memset(iFatTable,0,iFatTableBytes);
       
   152 	*((TUint32*)iFatTable) = 0xFFFFFFF8 ; 
       
   153 	iBootSector.BPB_SecPerClus = aSecPerClus;
       
   154 	*((TUint16*)iBootSector.BPB_RsvdSecCnt) = 0x0001 ;
       
   155 	*((TUint16*)iBootSector.BPB_RootEntCnt) = KRootEntryCount ;
       
   156 	if(aTotalSectors > 0xFFFF)
       
   157 		*((TUint32*)iBootSector.BPB_TotSec32) = aTotalSectors; 
       
   158 	else
       
   159 		*((TUint16*)iBootSector.BPB_TotSec16) = (TUint16)aTotalSectors; 
       
   160 	TUint16 sectorsForFAT = (TUint16)((iFatTableBytes + aBytsPerSec - 1) / aBytsPerSec);
       
   161 	*((TUint16*)iBootSector.BPB_FATSz16) =  sectorsForFAT ; 
       
   162 	memcpy(iFatHeader.BS_FilSysType,"FAT16   ",sizeof(iFatHeader.BS_FilSysType));
       
   163 }
       
   164 void TFatImgGenerator::InitAsFat32(TUint32 aTotalSectors,TUint8 aSecPerClus,TUint16 aBytsPerSec) { 
       
   165 	
       
   166 	TUint32 numOfClusters;
       
   167 	if(aSecPerClus == 0) {
       
   168 		//Auto-calc the SecPerClus
       
   169 		// FAT32 ,Count of clusters must >= 65525, however , to avoid the "off by xx" warning, 
       
   170 		// proprositional value >= (65525 + 16)			
       
   171 		if(aTotalSectors < (65525 + 16)) { //when SecPerClus is 1, numOfClusters eq to aTotalSectors
       
   172 			iType = EFatUnknown ;
       
   173 			Print(EError,"Size is too small for FAT32, please use the FAT16 format, or set the data size bigger!\n");
       
   174 			return ;
       
   175 		}
       
   176 
       
   177 		TUint8 secPerClusMax = KMaxClusterBytes / aBytsPerSec; 
       
   178 		aSecPerClus = secPerClusMax;
       
   179 		while(aSecPerClus > 1){
       
   180 			numOfClusters = (aTotalSectors + aSecPerClus - 1) / aSecPerClus ;
       
   181 			if (numOfClusters >= (65525 + 16)) {
       
   182 				break;
       
   183 			}
       
   184 			aSecPerClus >>= 1 ; 
       
   185 		}	
       
   186 	}
       
   187 	else {
       
   188 		if( (aSecPerClus * aBytsPerSec) > KMaxClusterBytes){
       
   189 			Print(EError,"Cluster too large!\n");
       
   190 			iType = EFatUnknown;
       
   191 			return ;
       
   192 		}
       
   193 		numOfClusters = (aTotalSectors + aSecPerClus - 1) / aSecPerClus;
       
   194 		if(numOfClusters < (65525 + 16)) {
       
   195             Print(EError,"Cluster count is too small for FAT32, please set a new small sector count of cluster or set the size bigger or use the FAT16 format!\n");
       
   196 			iType = EFatUnknown ;
       
   197 			return ;
       
   198 		}
       
   199 
       
   200 	}
       
   201 	iTotalClusters = (aTotalSectors + aSecPerClus - 1) / aSecPerClus ;
       
   202 	iFatTableBytes = ((iTotalClusters << 2) +  aBytsPerSec - 1) & (~(aBytsPerSec - 1));
       
   203 	iFatTable = new(std::nothrow) char[iFatTableBytes];
       
   204 	if(!iFatTable) {
       
   205         Print(EError,"Memory allocation failed for FAT32 Table!\n");
       
   206 		iType = EFatUnknown ;
       
   207 		return ;
       
   208 	}
       
   209 	memset(iFatTable,0,iFatTableBytes);
       
   210 	TUint32* fat32table = reinterpret_cast<TUint32*>(iFatTable);
       
   211 	fat32table[0] = 0x0FFFFFF8 ;
       
   212 	fat32table[1] = 0x0FFFFFFF ;  
       
   213 	iBootSector.BPB_SecPerClus = aSecPerClus;
       
   214 	iBootSector.BPB_RsvdSecCnt[0] = 0x20 ;
       
   215 	*((TUint32*)iBootSector.BPB_TotSec32) = aTotalSectors; 
       
   216 	*((TUint32*)iFat32Ext.BPB_FATSz32) =  (iFatTableBytes + aBytsPerSec - 1) / aBytsPerSec; 
       
   217 	*((TUint32*)iFat32Ext.BPB_RootClus) = 2 ; 
       
   218 	*((TUint16*)iFat32Ext.BPB_FSInfo) = 1 ;
       
   219 	*((TUint16*)iFat32Ext.BPB_BkBootSec) = 6 ;
       
   220 	memcpy(iFatHeader.BS_FilSysType,"FAT32   ",sizeof(iFatHeader.BS_FilSysType));
       
   221 }
       
   222 
       
   223 bool TFatImgGenerator::Execute(TFSNode* aRootDir , const char* aOutputFile){
       
   224 	if(EFatUnknown == iType)
       
   225 		return false ;	
       
   226 	ofstream o(aOutputFile,ios_base::binary + ios_base::out + ios_base::trunc);
       
   227 	TUint32 writtenBytes = 0 ;
       
   228 	if(!o.is_open()) {
       
   229   	Print(EError,"Can not open \"%s\" for writing !\n",aOutputFile) ;
       
   230 		return false;
       
   231 	}
       
   232 	TUint16 bytsPerSector = *((TUint16*)iBootSector.BPB_BytsPerSec);
       
   233 	Interator it = iDataClusters.begin();
       
   234 	while(it != iDataClusters.end()){
       
   235 		TFatCluster* cluster = *it ;
       
   236 		delete cluster;
       
   237 		it++;
       
   238 	}
       
   239 	iDataClusters.clear();
       
   240 	Print(EAlways,"Filesystem ready.\nWriting Header...");
       
   241 	
       
   242 	if(EFat16 == iType){		 
       
   243 		char* header = new(std::nothrow) char[bytsPerSector];
       
   244 		if(!header){
       
   245       Print(EError,"Can not allocate memory for FAT16 header!\n");
       
   246 			o.close();
       
   247 			return false ;
       
   248 		}
       
   249 		int offset = 0;
       
   250 		memcpy(header,&iBootSector,sizeof(iBootSector));
       
   251 		offset = sizeof(iBootSector);
       
   252 		memcpy(&header[offset],&iFatHeader,sizeof(iFatHeader));
       
   253 		offset += sizeof(iFatHeader);
       
   254 		memset(&header[offset],0,bytsPerSector - offset);
       
   255 		*((TUint16*)(&header[510])) = 0xAA55 ;
       
   256 
       
   257 		o.write(header,bytsPerSector); 
       
   258 		writtenBytes +=  bytsPerSector;
       
   259 		delete []header ;		 
       
   260 		TUint16 rootDirSectors = (KRootEntryCount * 32) / bytsPerSector ;
       
   261 		TUint16 rootDirClusters = (rootDirSectors + iBootSector.BPB_SecPerClus - 1) /iBootSector.BPB_SecPerClus;		 
       
   262 		TUint32 rootDirBytes = KRootEntryCount * 32;
       
   263 		TFatCluster* rootDir = new(std::nothrow) TFatCluster(0,rootDirClusters);
       
   264 		rootDir->Init(rootDirBytes);
       
   265 		iDataClusters.push_back(rootDir);
       
   266 		aRootDir->WriteDirEntries(KRootClusterIndex,rootDir->GetData());
       
   267 		 
       
   268 		TUint index = 2 ;
       
   269 		Print(EAlways,"    OK.\nPreparing cluster list..."); 
       
   270 		TFSNode* child = aRootDir->GetFirstChild() ; 
       
   271 		while(child){
       
   272 			if(!PrepareClusters(index,child)){
       
   273                 Print(EAlways,"    Failed.\nError:Image size is expected to be big enough for all the files.\n");
       
   274 				return false ;
       
   275 			}
       
   276 			child = child->GetSibling() ;
       
   277 		}
       
   278 	}
       
   279 	else if(EFat32 == iType){
       
   280 
       
   281 		TUint headerSize = ( bytsPerSector << 5 ); // 32 reserved sectors for fat32
       
   282 		char* header = new(std::nothrow) char[headerSize];
       
   283 		if(!header){
       
   284             Print(EError,"Can not allocate memory for FAT32 header!\n");
       
   285 			o.close();
       
   286 			return false ;
       
   287 		}
       
   288 		memset(header,0,headerSize);
       
   289 
       
   290 		int offset = 0;
       
   291 		memcpy(header,&iBootSector,sizeof(iBootSector));
       
   292 		offset = sizeof(iBootSector);
       
   293 		memcpy(&header[offset],&iFat32Ext,sizeof(iFat32Ext));
       
   294 		offset += sizeof(iFat32Ext);
       
   295 		memcpy(&header[offset],&iFatHeader,sizeof(iFatHeader));
       
   296 		offset += sizeof(iFatHeader);
       
   297 
       
   298 		TFAT32FSInfoSector* fsinfo = reinterpret_cast<TFAT32FSInfoSector*>(&header[bytsPerSector]);
       
   299 		*((TUint32*)fsinfo->FSI_LeadSig) = 0x41615252 ;
       
   300 		*((TUint32*)fsinfo->FSI_StrucSig) = 0x61417272 ;
       
   301 		memset(fsinfo->FSI_Free_Count,0xFF,8);
       
   302 		char* tailed = header + 510 ;
       
   303 		for(int i = 0 ; i < 32 ; i++ , tailed += bytsPerSector )
       
   304 			*((TUint16*)tailed) = 0xAA55 ;		
       
   305 		 
       
   306 		TUint index = 2 ;		
       
   307 		Print(EAlways,"    OK.\nPreparing cluster list...");
       
   308 		if(!PrepareClusters(index,aRootDir)) {
       
   309             Print(EAlways,"    Failed.\nERROR: Image size is expected to be big enough for all the files.\n");
       
   310 			delete []header ;
       
   311 			return false;
       
   312 		}
       
   313 	 
       
   314  
       
   315 		*(TUint32*)(fsinfo->FSI_Free_Count) = iTotalClusters - index + 3;
       
   316 		*(TUint32*)(fsinfo->FSI_Nxt_Free) =  index ;
       
   317 
       
   318 		// write bakup boot sectors
       
   319 		memcpy(&header[bytsPerSector * 6],header,(bytsPerSector << 1));
       
   320 		o.write(header,headerSize); 
       
   321 		writtenBytes += headerSize;
       
   322 		delete []header ;
       
   323 	}
       
   324 	//iDataClusters.sort();
       
   325 	it = iDataClusters.end() ;
       
   326 	it -- ;
       
   327 	int clusters = (*it)->GetIndex() + (*it)->ActualClusterCount() - 1;
       
   328 
       
   329 	Print(EAlways,"    OK.\n%d clusters of data need to be written.\nWriting Fat table...",clusters);
       
   330 	for(TUint8 w = 0 ; w < iBootSector.BPB_NumFATs ; w++){
       
   331 		o.write(iFatTable,iFatTableBytes);	 
       
   332 		if(o.bad() || o.fail()){
       
   333 			Print(EAlways,"\nERROR:Writting failed. Please check the filesystem\n");
       
   334 			delete []iFatTable,
       
   335 			o.close();
       
   336 			return false ;
       
   337 		}
       
   338 		writtenBytes += iFatTableBytes;
       
   339 	}
       
   340 	char* buffer = new(std::nothrow) char[KBufferedIOBytes];
       
   341 	if(!buffer){
       
   342     Print(EError,"Can not allocate memory for I/O buffer !\n");
       
   343 		o.close();
       
   344 		return false ;
       
   345 	}
       
   346 	o.flush();
       
   347 	Print(EAlways,"    OK.\nWriting clusters data...");
       
   348  
       
   349 	int bytesInBuffer = 0;
       
   350 	int writeTimes = 24; 
       
   351  
       
   352 	TFatCluster* lastClust = 0 ;	
       
   353 	for(it = iDataClusters.begin(); it != iDataClusters.end() ; it++ ){
       
   354 		TFatCluster* cluster = *it ;
       
   355 		TUint fileSize = cluster->GetSize(); 		 
       
   356 		TUint toProcess = cluster->ActualClusterCount() * iBytsPerClus ; 
       
   357 		if(toProcess > KBufferedIOBytes){ // big file 
       
   358 			if(bytesInBuffer > 0){
       
   359 				o.write(buffer,bytesInBuffer); 
       
   360 				if(o.bad() || o.fail()){
       
   361 					Print(EError,"Writting failed.\n");
       
   362 					delete []buffer,
       
   363 					o.close();
       
   364 					return false ;
       
   365 				}
       
   366 				writtenBytes += bytesInBuffer;
       
   367 				bytesInBuffer = 0;
       
   368 				Print(EAlways,".");
       
   369 				writeTimes ++ ;
       
   370 				if((writeTimes % KCharsOfCmdWndLine) == 0){
       
   371 					o.flush();
       
   372 					cout << endl ;
       
   373 				} 
       
   374 			}
       
   375 			if(cluster->IsLazy()){
       
   376 				ifstream ifs(cluster->GetFileName(), ios_base::binary + ios_base::in);
       
   377 				if(!ifs.is_open()){
       
   378 					Print(EError,"Can not open file \"%s\"\n",cluster->GetFileName()) ;
       
   379 					o.close();
       
   380 					delete []buffer;
       
   381 					return false ;
       
   382 				}
       
   383 				if(!ifs.good()) ifs.clear(); 
       
   384 				TUint processedBytes = 0 ; 
       
   385 
       
   386 				while(processedBytes < 	fileSize){
       
   387 					TUint ioBytes = fileSize - processedBytes ;
       
   388 					if(ioBytes > KBufferedIOBytes)
       
   389 						ioBytes = KBufferedIOBytes;
       
   390 					ifs.read(buffer,ioBytes);
       
   391 					processedBytes += ioBytes;					 
       
   392 					o.write(buffer,ioBytes); 
       
   393 					if(o.bad() || o.fail()){
       
   394 						Print(EError,"Writting failed.\n");
       
   395 						delete []iFatTable,
       
   396 						o.close();
       
   397 						return false ;
       
   398 					}
       
   399 					writtenBytes += ioBytes;
       
   400 					Print(EAlways,".");
       
   401 					writeTimes ++ ;
       
   402 					if((writeTimes % KCharsOfCmdWndLine) == 0){
       
   403 						o.flush();
       
   404 						Print(EAlways,"\n") ;
       
   405 					}
       
   406 
       
   407 				}
       
   408 				TUint paddingBytes = toProcess - processedBytes;
       
   409 				if( paddingBytes > 0 ){
       
   410 					memset(buffer,0,paddingBytes);
       
   411 					o.write(buffer,paddingBytes);
       
   412 					if(o.bad() || o.fail()){
       
   413 						Print(EError,"Writting failed.\n");
       
   414 						delete []buffer,
       
   415 						o.close();
       
   416 						return false ;
       
   417 					}
       
   418 					writtenBytes += paddingBytes;
       
   419 				}
       
   420 				ifs.close();
       
   421 
       
   422 			}
       
   423 			else {
       
   424 				// impossible 
       
   425         Print(EError,"Unexpected result!\n");
       
   426 				o.close();
       
   427 				delete []buffer;
       
   428 				return false ;
       
   429 			}
       
   430 		}
       
   431 		else {
       
   432 			if(toProcess > (KBufferedIOBytes - bytesInBuffer)){
       
   433 				o.write(buffer,bytesInBuffer); 
       
   434 				if(o.bad() || o.fail()){
       
   435 					Print(EError,"Writting failed.\n");
       
   436 					delete []buffer,
       
   437 					o.close();
       
   438 					return false ;
       
   439 				}
       
   440 				writtenBytes += bytesInBuffer;
       
   441 				Print(EAlways,".");
       
   442 				writeTimes ++ ;
       
   443 				if((writeTimes % KCharsOfCmdWndLine) == 0){
       
   444 					o.flush();
       
   445 					cout  << endl ;
       
   446 				}
       
   447 				bytesInBuffer = 0;
       
   448 			}
       
   449 			if(cluster->IsLazy()){
       
   450 				ifstream ifs(cluster->GetFileName(), ios_base::binary + ios_base::in);
       
   451 				if(!ifs.is_open()){
       
   452 				    Print(EError,"Can not open file \"%s\"\n",cluster->GetFileName()) ;
       
   453 					o.close();
       
   454 					delete []buffer;
       
   455 					return false ;
       
   456 				}
       
   457 				if(!ifs.good()) ifs.clear(); 
       
   458 				ifs.read(&buffer[bytesInBuffer],fileSize);
       
   459 				bytesInBuffer += fileSize;
       
   460 				if(toProcess > fileSize) { // fill padding bytes 
       
   461 					memset(&buffer[bytesInBuffer],0,toProcess - fileSize);
       
   462 					bytesInBuffer += (toProcess - fileSize);
       
   463 				}
       
   464 				ifs.close();
       
   465 
       
   466 			}
       
   467 			else{
       
   468 				if(toProcess != cluster->GetSize() && cluster->GetIndex() != KRootClusterIndex){
       
   469         	Print(EError,"Unexpected size!\n");
       
   470 					o.close();
       
   471 					delete []buffer;
       
   472 					return false ;
       
   473 				}
       
   474 				memcpy(&buffer[bytesInBuffer],cluster->GetData(),cluster->GetSize());
       
   475 				bytesInBuffer += cluster->GetSize();
       
   476 			}
       
   477 
       
   478 		} 
       
   479 		lastClust = cluster ;	 
       
   480 
       
   481 	}
       
   482 	if(bytesInBuffer > 0){
       
   483 		o.write(buffer,bytesInBuffer);
       
   484 		if(o.bad() || o.fail()){
       
   485 			Print(EError,"Writting failed.\n");
       
   486 			delete []buffer,
       
   487 			o.close();
       
   488 			return false ;
       
   489 		}
       
   490 		writtenBytes += bytesInBuffer;
       
   491 		o.flush();
       
   492 	}
       
   493 	Print(EAlways,"\nDone.\n\n");
       
   494 	o.close();
       
   495 
       
   496 	return true ;
       
   497 }
       
   498 bool TFatImgGenerator::PrepareClusters(TUint& aNextClusIndex,TFSNode* aNode) { 
       
   499 	TUint sizeOfItem = aNode->GetSize();
       
   500 	TUint clusters = (sizeOfItem + iBytsPerClus - 1) / iBytsPerClus;
       
   501 	
       
   502 	if(iTotalClusters < aNextClusIndex + clusters)
       
   503 		return false ;
       
   504 		
       
   505 	TUint16* fat16Table = reinterpret_cast<TUint16*>(iFatTable);
       
   506 	TUint32* fat32Table = reinterpret_cast<TUint32*>(iFatTable);	 
       
   507 	 
       
   508 	for(TUint i = aNextClusIndex + clusters - 1 ; i > aNextClusIndex  ; i--){
       
   509 		if(iType == EFat16)
       
   510 			fat16Table[i - 1] = i ;
       
   511 		else
       
   512 			fat32Table[i - 1] = i ;
       
   513 	}
       
   514 	if(iType == EFat16)
       
   515 		fat16Table[aNextClusIndex + clusters - 1] = 0xffff ;
       
   516 	else
       
   517 		fat32Table[aNextClusIndex + clusters - 1] = 0x0fffffff ;
       
   518 		
       
   519 	TFatCluster* cluster = new TFatCluster(aNextClusIndex,clusters);
       
   520 	if(aNode->IsDirectory()) {
       
   521     TUint bytes = clusters * iBytsPerClus ;
       
   522 		cluster->Init(bytes);
       
   523 		aNode->WriteDirEntries(aNextClusIndex,cluster->GetData());
       
   524 	}
       
   525 	else {
       
   526 		cluster->LazyInit(aNode->GetPCSideName(),sizeOfItem);
       
   527 		aNode->WriteDirEntries(aNextClusIndex,NULL);
       
   528 	}
       
   529 	iDataClusters.push_back(cluster);
       
   530  
       
   531 	aNextClusIndex += clusters;
       
   532 	if(aNode->GetFirstChild()){
       
   533 		if(!PrepareClusters(aNextClusIndex,aNode->GetFirstChild()))
       
   534 			return false ;
       
   535 	}
       
   536 	if(aNode->GetSibling()){
       
   537 		if(!PrepareClusters(aNextClusIndex,aNode->GetSibling()))
       
   538 			return false;
       
   539 	}
       
   540 	return true ;
       
   541 }