|
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 } |