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