|
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // f32\sfat\sl_file.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 |
|
19 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
20 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
21 //!! |
|
22 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it |
|
23 //!! |
|
24 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
25 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
26 |
|
27 |
|
28 #include "sl_std.h" |
|
29 #include "sl_cache.h" |
|
30 #include <e32math.h> |
|
31 |
|
32 const TInt KSeekIndexSize=128; // Cache 128 clusters |
|
33 const TInt KSeekIndexSizeLog2=7; |
|
34 const TInt KFirstClusterNum=2; |
|
35 |
|
36 CFatFileCB::CFatFileCB() |
|
37 { |
|
38 |
|
39 __PRINT1(_L("CFatFileCB created 0x%x"),this); |
|
40 } |
|
41 |
|
42 CFatFileCB::~CFatFileCB() |
|
43 { |
|
44 __PRINT1(_L("CFatFileCB deleted 0x%x"),this); |
|
45 |
|
46 //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction. |
|
47 //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll() |
|
48 //-- implies valid iMount. |
|
49 const CMountCB* pMount = &Mount(); |
|
50 if(pMount) |
|
51 {//-- do some finalisation work if CMountCB is valid |
|
52 if (iAtt&KEntryAttModified) |
|
53 TRAP_IGNORE(FlushAllL()); |
|
54 } |
|
55 |
|
56 delete[] iSeekIndex; |
|
57 } |
|
58 |
|
59 |
|
60 void CFatFileCB::CreateSeekIndex() |
|
61 // |
|
62 // Create a seek index |
|
63 // |
|
64 { |
|
65 |
|
66 iSeekIndex = new TUint32[KSeekIndexSize]; |
|
67 if (iSeekIndex == NULL) |
|
68 return; |
|
69 |
|
70 Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize); |
|
71 |
|
72 iSeekIndexSize=CalcSeekIndexSize(Size()); |
|
73 } |
|
74 |
|
75 TInt CFatFileCB::SeekToPosition(TInt aNewRelCluster,TInt aClusterOffset) |
|
76 // |
|
77 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster |
|
78 // Return aNewRelCluster-aCurrentPos.iCluster |
|
79 // |
|
80 { |
|
81 TInt clusterOffset=aClusterOffset; |
|
82 TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1; |
|
83 __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall)); |
|
84 |
|
85 while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0) |
|
86 { |
|
87 seekPos--; |
|
88 clusterOffset--; |
|
89 } |
|
90 if (clusterOffset==0) // Counted back to the current cluster |
|
91 return(aClusterOffset); |
|
92 if (seekPos<0) |
|
93 { |
|
94 iCurrentPos.iCluster=iStartCluster; |
|
95 return(aNewRelCluster); |
|
96 } |
|
97 |
|
98 iCurrentPos.iCluster=iSeekIndex[seekPos]; |
|
99 return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize)); |
|
100 } |
|
101 |
|
102 void CFatFileCB::SetSeekIndexValueL(TInt aRelCluster,TInt aStoredCluster) |
|
103 // |
|
104 // Sets a value in the seekindex |
|
105 // |
|
106 { |
|
107 |
|
108 TInt seekPos=(aRelCluster>>iSeekIndexSize)-1; |
|
109 __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall)); |
|
110 __ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2)); |
|
111 iSeekIndex[seekPos] = aStoredCluster; |
|
112 } |
|
113 |
|
114 TBool CFatFileCB::IsSeekBackwards(TUint aPos) |
|
115 // |
|
116 // Return true if aPos<currentPos |
|
117 // |
|
118 { |
|
119 |
|
120 TUint cluster=iCurrentPos.iCluster<<ClusterSizeLog2(); |
|
121 TInt offset=ClusterRelativePos(iCurrentPos.iPos); |
|
122 TUint currentPos=cluster+offset; |
|
123 return(aPos<currentPos); |
|
124 } |
|
125 |
|
126 void CFatFileCB::CheckPosL(TUint aPos) |
|
127 // |
|
128 // Check that the file is positioned correctly. |
|
129 // If aPos<currentPos attempt to guess the new position. |
|
130 // |
|
131 { |
|
132 __PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos); |
|
133 if (aPos==iCurrentPos.iPos) |
|
134 return; |
|
135 __ASSERT_DEBUG(aPos <= (TUint)Size(), Fault(EFatFilePosBeyondEnd)); |
|
136 |
|
137 if (iFileSizeModified && IsSeekBackwards(aPos)) |
|
138 FlushDataL(); |
|
139 |
|
140 TUint newRelCluster=aPos>>ClusterSizeLog2(); |
|
141 if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) ) |
|
142 newRelCluster--; |
|
143 TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2(); |
|
144 if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) ) |
|
145 oldRelCluster--; |
|
146 TInt clusterOffset=newRelCluster-oldRelCluster; |
|
147 TInt oldCluster=iCurrentPos.iCluster; |
|
148 iCurrentPos.iPos=aPos; |
|
149 if (clusterOffset==0) |
|
150 return; |
|
151 TInt seekOffset=clusterOffset; |
|
152 if (iSeekIndex!=NULL) |
|
153 { // Can alter iCurrentPos.iCluster |
|
154 seekOffset=SeekToPosition(newRelCluster,seekOffset); |
|
155 if (seekOffset==0) |
|
156 return; |
|
157 } |
|
158 if (clusterOffset==-1 && seekOffset!=1) |
|
159 { // Check previous cluster |
|
160 TInt cluster=oldCluster-1; |
|
161 if (FAT().GetNextClusterL(cluster) && cluster==oldCluster) |
|
162 { |
|
163 iCurrentPos.iCluster=oldCluster-1; |
|
164 return; |
|
165 } |
|
166 } |
|
167 if (seekOffset<0) |
|
168 { |
|
169 seekOffset=newRelCluster; |
|
170 iCurrentPos.iCluster=iStartCluster; |
|
171 } |
|
172 while (seekOffset--) |
|
173 { |
|
174 if (!FAT().GetNextClusterL(iCurrentPos.iCluster)) |
|
175 { |
|
176 __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1")); |
|
177 User::Leave(KErrCorrupt); |
|
178 } |
|
179 TInt cluster=newRelCluster-seekOffset; |
|
180 if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster) |
|
181 SetSeekIndexValueL(cluster,iCurrentPos.iCluster); |
|
182 } |
|
183 } |
|
184 |
|
185 void CFatFileCB::SetL(const TFatDirEntry& aFatDirEntry,TShare aShare,const TEntryPos& aPos) |
|
186 // |
|
187 // Initialize FileCB from entry data |
|
188 // |
|
189 { |
|
190 |
|
191 __PRINT(_L("CFatFileCB::SetL")); |
|
192 SetSize(aFatDirEntry.Size()); |
|
193 iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry); |
|
194 iStartCluster=iCurrentPos.iCluster; |
|
195 iCurrentPos.iPos=0; |
|
196 iAtt=aFatDirEntry.Attributes(); |
|
197 iModified= aFatDirEntry.Time(FatMount().TimeOffset()); |
|
198 iShare=aShare; |
|
199 iFileDirPos=aPos; |
|
200 |
|
201 SetMaxSupportedSize(KMaxSupportedFatFileSize); |
|
202 } |
|
203 |
|
204 //----------------------------------------------------------------------------- |
|
205 // from CFileCB::MExtendedFileInterface |
|
206 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset) |
|
207 { |
|
208 __PRINT2(_L("CFatFileCB::ReadL aFilePos=%LU aLength=%d"),aPos,aLength); |
|
209 |
|
210 if((TUint64)aPos > KMaxSupportedFatFileSize-1) |
|
211 User::Leave(KErrNotSupported); //-- max. position in the file is 0xFFFFFFFE |
|
212 |
|
213 FatMount().CheckStateConsistentL(); |
|
214 |
|
215 CheckPosL(I64LOW(aPos)); |
|
216 |
|
217 const TUint startPos = iCurrentPos.iPos; |
|
218 const TUint curSize = (TUint)Size(); |
|
219 const TUint length = (TUint)aLength; |
|
220 |
|
221 if((startPos + length > curSize) || (startPos > startPos + length) ) |
|
222 aLength=curSize-startPos; |
|
223 |
|
224 FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset); |
|
225 aLength=iCurrentPos.iPos-startPos; |
|
226 } |
|
227 |
|
228 |
|
229 void CFatFileCB::ReadL(TInt aFilePos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage) |
|
230 { |
|
231 ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0); |
|
232 } |
|
233 |
|
234 //----------------------------------------------------------------------------- |
|
235 // from CFileCB::MExtendedFileInterface |
|
236 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset) |
|
237 { |
|
238 __PRINT2(_L("CFatFileCB::WriteL aFilePos=%LU aLength=%d"),aPos,aLength); |
|
239 // FAT supports 32 bits only for file size |
|
240 TUint64 endPos = aPos + aLength; |
|
241 if(endPos > KMaxSupportedFatFileSize) |
|
242 User::Leave(KErrNotSupported); |
|
243 |
|
244 FatMount().CheckStateConsistentL(); |
|
245 FatMount().CheckWritableL(); |
|
246 const TUint pos = I64LOW(aPos); |
|
247 CheckPosL(pos); |
|
248 |
|
249 const TUint startCluster = (TUint)iStartCluster; |
|
250 const TUint length = (TUint)aLength; |
|
251 |
|
252 endPos = iCurrentPos.iPos + length; |
|
253 if ((endPos > (TUint)Size()) || |
|
254 (iCurrentPos.iPos > endPos) ) // Overflow condition |
|
255 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
|
256 |
|
257 TUint startPos=iCurrentPos.iPos; |
|
258 TInt badcluster=0; |
|
259 TInt goodcluster=0; |
|
260 |
|
261 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster)); |
|
262 |
|
263 if (ret == KErrCorrupt || ret == KErrDied) |
|
264 { |
|
265 if(startCluster == 0) |
|
266 { //Empty File, revert all the clusters allocated. |
|
267 TInt cluster = iStartCluster; |
|
268 iStartCluster = 0; |
|
269 SetSize(0); |
|
270 FlushAllL(); |
|
271 |
|
272 iCurrentPos.iCluster = 0; |
|
273 iCurrentPos.iPos = 0; |
|
274 |
|
275 FAT().FreeClusterListL(cluster); |
|
276 FAT().FlushL(); |
|
277 } |
|
278 else |
|
279 { //Calculate the clusters required based on file size, revert extra clusters if allocated. |
|
280 const TUint curSize = (TUint)Size(); |
|
281 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
|
282 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
|
283 { |
|
284 ClustersNeeded++; |
|
285 } |
|
286 |
|
287 TInt cluster = iStartCluster; |
|
288 while(--ClustersNeeded) |
|
289 { |
|
290 FAT().GetNextClusterL(cluster); |
|
291 } |
|
292 |
|
293 iCurrentPos.iCluster = cluster; |
|
294 |
|
295 if (FAT().GetNextClusterL(cluster)) |
|
296 { |
|
297 FAT().FreeClusterListL(cluster); |
|
298 } |
|
299 |
|
300 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
|
301 FAT().FlushL(); |
|
302 } |
|
303 } |
|
304 |
|
305 User::LeaveIfError(ret); |
|
306 |
|
307 if(badcluster != 0) |
|
308 { |
|
309 if(iStartCluster == badcluster) |
|
310 { |
|
311 iStartCluster = goodcluster; |
|
312 FlushStartClusterL(); |
|
313 } |
|
314 else |
|
315 { |
|
316 TInt aCluster = iStartCluster; |
|
317 do |
|
318 { |
|
319 if((TUint)badcluster == FAT().ReadL(aCluster)) |
|
320 { |
|
321 FAT().WriteL(aCluster, goodcluster); |
|
322 FAT().FlushL(); |
|
323 break; |
|
324 } |
|
325 } |
|
326 while(FAT().GetNextClusterL(aCluster)); |
|
327 } |
|
328 } |
|
329 aLength=iCurrentPos.iPos-startPos; |
|
330 |
|
331 if(FatMount().IsRuggedFSys() && pos+(TUint)aLength>(TUint)Size()) |
|
332 { |
|
333 WriteFileSizeL(pos+aLength); |
|
334 } |
|
335 |
|
336 } |
|
337 |
|
338 |
|
339 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage) |
|
340 { |
|
341 WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0); |
|
342 } |
|
343 |
|
344 |
|
345 |
|
346 //----------------------------------------------------------------------------- |
|
347 |
|
348 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize) |
|
349 // |
|
350 // Resize the seek index to accomodate a larger or smaller filesize |
|
351 // Assumes KSeekIndexSize is a power of 2. |
|
352 // |
|
353 { |
|
354 |
|
355 TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult); |
|
356 |
|
357 |
|
358 TInt index=0; |
|
359 TInt indexEnd=KSeekIndexSize; |
|
360 TInt newValEnd=maxNewIndex; |
|
361 |
|
362 if (iSeekIndexSize<aNewMult) |
|
363 { |
|
364 TInt newVal=index; |
|
365 TInt step=1<<(aNewMult-iSeekIndexSize); |
|
366 index+=step-1; |
|
367 while(index<indexEnd && newVal<newValEnd) |
|
368 { |
|
369 iSeekIndex[newVal] = iSeekIndex[index]; |
|
370 newVal++; |
|
371 index+=step; |
|
372 } |
|
373 while(newVal<indexEnd) |
|
374 iSeekIndex[newVal++] = 0; |
|
375 } |
|
376 else |
|
377 { |
|
378 TInt diffSize = iSeekIndexSize-aNewMult; |
|
379 TInt oldVal=(KSeekIndexSize>>diffSize) - 1; |
|
380 TInt newVal=indexEnd-1; |
|
381 TInt skip=(1<<diffSize)-1; |
|
382 |
|
383 if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2) |
|
384 { |
|
385 ClearIndex(0); //-- Invalidate every entry. |
|
386 } |
|
387 else |
|
388 { |
|
389 while(newVal>=index) |
|
390 { |
|
391 |
|
392 iSeekIndex[newVal--] = iSeekIndex[oldVal--]; |
|
393 |
|
394 |
|
395 for(TInt i=skip;i>0;i--) |
|
396 { |
|
397 iSeekIndex[newVal--] = 0; |
|
398 |
|
399 } |
|
400 } |
|
401 } |
|
402 } |
|
403 iSeekIndexSize=aNewMult; |
|
404 } |
|
405 |
|
406 |
|
407 /** |
|
408 Zero freed clusters in the index |
|
409 |
|
410 @param aNewSize new size of the file that the index corresponds to. |
|
411 if = 0 all existing index will be zero filled |
|
412 */ |
|
413 void CFatFileCB::ClearIndex(TUint aNewSize) |
|
414 { |
|
415 |
|
416 if (!iSeekIndex) |
|
417 return; |
|
418 |
|
419 if(aNewSize==0) |
|
420 { |
|
421 //-- zero fill all the array |
|
422 Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32)); |
|
423 return; |
|
424 } |
|
425 |
|
426 // Files that fill up a cluster exactly do not have a trailing empty |
|
427 // cluster. So the entry for that position must also be invalidated |
|
428 aNewSize--; |
|
429 TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2()); |
|
430 |
|
431 TInt indexLen=KSeekIndexSize-firstInvalidIndex; |
|
432 |
|
433 Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32)); |
|
434 } |
|
435 |
|
436 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize) |
|
437 // |
|
438 // Find the nearest power of 2 > aSize |
|
439 // |
|
440 { |
|
441 TInt count = 0; |
|
442 const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128 |
|
443 if (aSize<=indexSize) |
|
444 return(count); |
|
445 |
|
446 while((aSize>>=1)>0) |
|
447 { |
|
448 count++; |
|
449 } |
|
450 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
|
451 } |
|
452 |
|
453 //----------------------------------------------------------------------------- |
|
454 |
|
455 void CFatFileCB::SetSizeL(TInt64 aSize) |
|
456 { |
|
457 __PRINT(_L("CFatFileCB::SetSizeL")); |
|
458 |
|
459 // FAT supports 32 bits only for file size |
|
460 if (I64HIGH(aSize)) |
|
461 User::Leave(KErrNotSupported); |
|
462 |
|
463 if(FatMount().IsRuggedFSys()) |
|
464 DoSetSizeL(I64LOW(aSize),ETrue); |
|
465 else |
|
466 DoSetSizeL(I64LOW(aSize),EFalse); |
|
467 } |
|
468 |
|
469 |
|
470 void CFatFileCB::SetSizeL(TInt aSize) |
|
471 // |
|
472 // Envelope function around DoSetSizeL to enable aSize to |
|
473 // be written to disk for rugged fat file system |
|
474 // |
|
475 { |
|
476 SetSizeL(TInt64(aSize)); |
|
477 } |
|
478 |
|
479 void CFatFileCB::DoSetSizeL(TUint aSize,TBool aIsSizeWrite) |
|
480 // |
|
481 // Extend or truncate the file. |
|
482 // Expects the modified attribute and iSize are set afterwards. |
|
483 // Does not alter iCurrentPos, the current file position. |
|
484 // Writes size of file to disk if aIsSizeWrite set |
|
485 // |
|
486 { |
|
487 __PRINT2(_L("CFatFileCB::DoSetSizeL sz:%d, fileWrite=%d"),aSize ,aIsSizeWrite); |
|
488 |
|
489 FatMount().CheckStateConsistentL(); |
|
490 FatMount().CheckWritableL(); |
|
491 |
|
492 |
|
493 // Can not change the file size if it is clamped |
|
494 if(Mount().IsFileClamped(MAKE_TINT64(0,iStartCluster)) > 0) |
|
495 User::Leave(KErrInUse); |
|
496 |
|
497 iFileSizeModified=ETrue; |
|
498 |
|
499 TInt newIndexMult=CalcSeekIndexSize(aSize); |
|
500 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
|
501 ResizeIndex(newIndexMult,aSize); |
|
502 if (aSize == 0) |
|
503 { |
|
504 if (Size() != 0) |
|
505 { |
|
506 ClearIndex(0); //-- clear seek index array |
|
507 TInt cluster=iStartCluster; |
|
508 iStartCluster = 0; |
|
509 SetSize(0); |
|
510 FlushAllL(); |
|
511 CheckPosL(0); |
|
512 FAT().FreeClusterListL(cluster); |
|
513 FAT().FlushL(); |
|
514 } |
|
515 return; |
|
516 } |
|
517 if (aSize<(TUint)Size()) |
|
518 { |
|
519 if(aIsSizeWrite) // write file size if decreasing |
|
520 WriteFileSizeL(aSize); |
|
521 CheckPosL(aSize); |
|
522 TInt cluster=iCurrentPos.iCluster; |
|
523 if (FAT().GetNextClusterL(cluster)) |
|
524 { |
|
525 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
|
526 FAT().FreeClusterListL(cluster); |
|
527 } |
|
528 ClearIndex(aSize); |
|
529 FAT().FlushL(); |
|
530 return; |
|
531 } |
|
532 |
|
533 TUint newSize=aSize>>ClusterSizeLog2(); // Number of clusters we now need |
|
534 if (aSize > (newSize<<ClusterSizeLog2())) |
|
535 newSize++; // File size is not an exact multiple of cluster size |
|
536 // Increment the number of clusters required to accomodate tail |
|
537 |
|
538 if (iStartCluster==0) |
|
539 { |
|
540 //-- FAT().FreeClusterHint() will give us a hint of the last free cluster |
|
541 ClearIndex(0); //-- clear seek index array |
|
542 TInt tempStartCluster=FAT().AllocateClusterListL(newSize, FAT().FreeClusterHint()); |
|
543 FAT().FlushL(); |
|
544 iCurrentPos.iCluster=tempStartCluster; |
|
545 iStartCluster=tempStartCluster; |
|
546 SetSize(aSize); |
|
547 FlushAllL(); |
|
548 } |
|
549 else |
|
550 { |
|
551 const TUint curSize = (TUint)Size(); |
|
552 TUint oldSize=curSize>>ClusterSizeLog2(); // Number of clusters we had previously |
|
553 if (curSize>(oldSize<<ClusterSizeLog2())) |
|
554 oldSize++; |
|
555 |
|
556 TInt newClusters=newSize-oldSize; // Number of clusters we need to prepare |
|
557 if (newClusters) |
|
558 { |
|
559 TEntryPos currentPos=iCurrentPos; |
|
560 CheckPosL(Size()); |
|
561 FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); |
|
562 iCurrentPos=currentPos; |
|
563 } |
|
564 FAT().FlushL(); |
|
565 if(aIsSizeWrite) // write file size if increasing |
|
566 WriteFileSizeL(aSize); |
|
567 } |
|
568 } |
|
569 |
|
570 //----------------------------------------------------------------------------- |
|
571 /** |
|
572 Set the entry's attributes and modified time. |
|
573 */ |
|
574 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
|
575 { |
|
576 __PRINT(_L("CFatFileCB::SetEntryL")); |
|
577 |
|
578 FatMount().CheckStateConsistentL(); |
|
579 FatMount().CheckWritableL(); |
|
580 |
|
581 TUint setAttMask=aSetAttMask&KEntryAttMaskSupported; |
|
582 if (setAttMask|aClearAttMask) |
|
583 { |
|
584 iAtt|=setAttMask; |
|
585 iAtt&=(~aClearAttMask); |
|
586 } |
|
587 if (aSetAttMask&KEntryAttModified) |
|
588 iModified=aTime; |
|
589 iAtt|=KEntryAttModified; |
|
590 } |
|
591 |
|
592 /** |
|
593 This is a RuggedFAT - specific method. Writes file size to the corresponding field of this |
|
594 file direcrory entry. |
|
595 */ |
|
596 void CFatFileCB::WriteFileSizeL(TUint aSize) |
|
597 { |
|
598 __PRINT(_L("CFatFileCB::WriteFileSizeL")); |
|
599 TEntryPos entryPos=iFileDirPos; |
|
600 entryPos.iPos+=_FOFF(SFatDirEntry,iSize); |
|
601 TPtrC8 size((TUint8*)&aSize,sizeof(TUint)); |
|
602 |
|
603 //-- use directory cache when dealing with directories |
|
604 FatMount().DirWriteL(entryPos,size); |
|
605 iFileSizeModified=EFalse; |
|
606 } |
|
607 |
|
608 //----------------------------------------------------------------------------- |
|
609 /** |
|
610 Flush file size, attributes, time etc. to the media. |
|
611 It doesn't matter if whole directory entry is being written of only part of it. Anyway, a single DOS |
|
612 dir. entry always fits into 1 sector. |
|
613 */ |
|
614 void CFatFileCB::FlushDataL() |
|
615 { |
|
616 __PRINT(_L("CFatFileCB::FlushDataL")); |
|
617 FlushAllL(); |
|
618 } |
|
619 |
|
620 //----------------------------------------------------------------------------- |
|
621 /** |
|
622 Flush the fide directory entry data: files size, attributes, time etc. |
|
623 */ |
|
624 void CFatFileCB::FlushAllL() |
|
625 { |
|
626 __PRINT(_L("CFatFileCB::FlushAllL()")); |
|
627 |
|
628 if (Mount().IsCurrentMount()==EFalse) |
|
629 User::Leave(KErrDisMounted); |
|
630 |
|
631 FatMount().CheckStateConsistentL(); |
|
632 FatMount().CheckWritableL(); |
|
633 |
|
634 TFatDirEntry entry; |
|
635 FatMount().ReadDirEntryL(iFileDirPos,entry); |
|
636 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
|
637 entry.SetAttributes(iAtt&KEntryAttMaskSupported); |
|
638 entry.SetSize(Size()); |
|
639 entry.SetTime(iModified, FatMount().TimeOffset()); |
|
640 entry.SetStartCluster(iStartCluster); |
|
641 |
|
642 TBool setNotify = FatMount().GetNotifyUser(); |
|
643 if(setNotify) |
|
644 { |
|
645 FatMount().SetNotifyOff(); // do not launch a notifier |
|
646 } |
|
647 |
|
648 TRAPD(ret, FatMount().WriteDirEntryL(iFileDirPos,entry)); |
|
649 |
|
650 if(setNotify) |
|
651 { |
|
652 FatMount().SetNotifyOn(); |
|
653 } |
|
654 |
|
655 User::LeaveIfError(ret); |
|
656 iAtt&=(~KEntryAttModified); |
|
657 iFileSizeModified=EFalse; |
|
658 } |
|
659 |
|
660 //----------------------------------------------------------------------------- |
|
661 |
|
662 /** |
|
663 Rename already opened file. |
|
664 @param aNewName new file name; all trailing dots from the name will be removed |
|
665 */ |
|
666 void CFatFileCB::RenameL(const TDesC& aNewName) |
|
667 { |
|
668 __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName); |
|
669 |
|
670 FatMount().CheckStateConsistentL(); |
|
671 FatMount().CheckWritableL(); |
|
672 |
|
673 const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name |
|
674 |
|
675 |
|
676 FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename,iFileDirPos); |
|
677 |
|
678 AllocBufferL(iFileName, fileName); |
|
679 |
|
680 if(!FatMount().IsRuggedFSys()) |
|
681 FAT().FlushL(); |
|
682 } |
|
683 |
|
684 |
|
685 //*********************************************************** |
|
686 //* BlockMap interface |
|
687 //*********************************************************** |
|
688 |
|
689 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos) |
|
690 // |
|
691 // Retrieves the block map of a given section of the file, in the FAT file system. |
|
692 // |
|
693 { |
|
694 __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos); |
|
695 |
|
696 if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) ) |
|
697 return KErrNotSupported; |
|
698 |
|
699 TUint startPos = I64LOW(aStartPos); |
|
700 TUint endPos = I64LOW(aEndPos); |
|
701 |
|
702 // aEndPos will always be >=0 at this point |
|
703 const TUint length = endPos - startPos; |
|
704 |
|
705 // Store the position of cluster zero in aInfo |
|
706 CFatMountCB& fatMount = FatMount(); |
|
707 |
|
708 TInt drvNo=-1; |
|
709 TBusLocalDrive* locDrv; |
|
710 if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives)) |
|
711 aInfo.iLocalDriveNumber=drvNo; |
|
712 else |
|
713 return KErrNotSupported; |
|
714 |
|
715 // Fetch the address of cluster 0 |
|
716 aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum); |
|
717 |
|
718 TRAPD(r, CheckPosL(startPos)); |
|
719 if (r != KErrNone) |
|
720 return r; |
|
721 |
|
722 aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos); |
|
723 aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2(); |
|
724 const TUint myStartPos = iCurrentPos.iPos; |
|
725 if ( myStartPos + length > (TUint)Size()) |
|
726 return KErrArgument; |
|
727 |
|
728 TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo)); |
|
729 if (r != KErrNone) |
|
730 return r; |
|
731 |
|
732 aStartPos = iCurrentPos.iPos; |
|
733 if ((I64LOW(aStartPos) == (TUint)Size()) || ( I64LOW(aStartPos) == (myStartPos + length))) |
|
734 return KErrCompletion; |
|
735 else |
|
736 return KErrNone; |
|
737 } |
|
738 |
|
739 |
|
740 |
|
741 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) |
|
742 { |
|
743 switch(aInterfaceId) |
|
744 { |
|
745 case EExtendedFileInterface: |
|
746 ((CFileCB::MExtendedFileInterface*&) aInterface) = this; |
|
747 return KErrNone; |
|
748 |
|
749 case EBlockMapInterface: |
|
750 aInterface = (CFileCB::MBlockMapInterface*) this; |
|
751 return KErrNone; |
|
752 |
|
753 case EGetLocalDrive: |
|
754 return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface); |
|
755 |
|
756 default: |
|
757 return CFileCB::GetInterface(aInterfaceId,aInterface,aInput); |
|
758 } |
|
759 } |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 /** |
|
765 Overwrites file's start cluster (iStartCluster) in its directory entry. |
|
766 */ |
|
767 void CFatFileCB::FlushStartClusterL() |
|
768 { |
|
769 __PRINT(_L("CFatFileCB::FlushStartClusterL")); |
|
770 |
|
771 CFatMountCB& mount = FatMount(); |
|
772 TFatDirEntry dirEntry; |
|
773 |
|
774 mount.ReadDirEntryL(iFileDirPos, dirEntry); //-- read this file's dir. entry |
|
775 dirEntry.SetStartCluster(iStartCluster); //-- set new start cluster |
|
776 mount.WriteDirEntryL(iFileDirPos, dirEntry);//-- write the entry back |
|
777 } |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |