170 if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster) |
175 if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster) |
171 SetSeekIndexValueL(cluster,iCurrentPos.iCluster); |
176 SetSeekIndexValueL(cluster,iCurrentPos.iCluster); |
172 } |
177 } |
173 } |
178 } |
174 |
179 |
175 void CFatFileCB::SetL(const TFatDirEntry& aFatDirEntry,TShare aShare,const TEntryPos& aPos) |
180 //----------------------------------------------------------------------------- |
176 // |
181 /** |
177 // Initialize FileCB from entry data |
182 Initialize FileCB from file's entry data. |
178 // |
183 |
179 { |
184 @param aFatDirEntry this file DOS dir entry. |
180 |
185 @param aFileDosEntryPos this file DOS entry dir. iterator in the parent directory. |
181 __PRINT(_L("CFatFileCB::SetL")); |
186 */ |
182 SetSize(aFatDirEntry.Size()); |
187 void CFatFileCB::SetupL(const TFatDirEntry& aFatDirEntry, const TEntryPos& aFileDosEntryPos) |
|
188 { |
|
189 __PRINT1(_L("CFatFileCB::SetupL[0x%x]"), this); |
|
190 |
|
191 |
|
192 //-- set up a file control block |
183 iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry); |
193 iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry); |
184 iStartCluster=iCurrentPos.iCluster; |
|
185 iCurrentPos.iPos=0; |
194 iCurrentPos.iPos=0; |
186 iAtt=aFatDirEntry.Attributes(); |
195 |
187 iModified= aFatDirEntry.Time(FatMount().TimeOffset()); |
196 SetAtt(aFatDirEntry.Attributes()); |
188 iShare=aShare; |
197 SetModified(aFatDirEntry.Time(FatMount().TimeOffset())); |
189 iFileDirPos=aPos; |
198 |
|
199 FCB_SetStartCluster(iCurrentPos.iCluster); |
|
200 FCB_SetFileSize(aFatDirEntry.Size()); |
|
201 |
|
202 iFileDosEntryPos = aFileDosEntryPos; |
190 |
203 |
191 SetMaxSupportedSize(KMaxSupportedFatFileSize); |
204 SetMaxSupportedSize(KMaxSupportedFatFileSize); |
192 } |
205 |
193 |
206 //-- create seek index |
194 //----------------------------------------------------------------------------- |
207 ASSERT(!iSeekIndex); |
195 // from CFileCB::MExtendedFileInterface |
208 CreateSeekIndex(); |
|
209 if(!iSeekIndex) |
|
210 User::Leave(KErrNoMemory); |
|
211 |
|
212 |
|
213 IndicateFileAttModified(EFalse); |
|
214 IndicateFileSizeModified(EFalse); |
|
215 IndicateFileTimeModified(EFalse); |
|
216 } |
|
217 |
|
218 //----------------------------------------------------------------------------- |
|
219 /** |
|
220 Read data from the file. |
|
221 |
|
222 @param aFilePos start read position within a file |
|
223 @param aLength how many bytes to read; on return will be how many bytes actually read |
|
224 @param aDes local buffer desctriptor |
|
225 @param aMessage from file server, used to write data to the buffer in different address space. |
|
226 @param aDesOffset offset within data descriptor where the data will be copied |
|
227 |
|
228 @leave on media read error |
|
229 |
|
230 */ |
196 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset) |
231 void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset) |
197 { |
232 { |
198 __PRINT2(_L("CFatFileCB::ReadL aFilePos=%LU aLength=%d"),aPos,aLength); |
233 __PRINT3(_L("CFatFileCB::ReadL[0x%x] pos=%LU len=%d"), this, aPos, aLength); |
199 |
234 |
200 if((TUint64)aPos > KMaxSupportedFatFileSize-1) |
235 if((TUint64)aPos > KMaxSupportedFatFileSize-1) |
201 User::Leave(KErrNotSupported); //-- max. position in the file is 0xFFFFFFFE |
236 User::Leave(KErrNotSupported); //-- max. position in the file is 0xFFFFFFFE |
202 |
237 |
203 FatMount().CheckStateConsistentL(); |
238 FatMount().CheckStateConsistentL(); |
204 |
239 |
205 CheckPosL(I64LOW(aPos)); |
240 CheckPosL(I64LOW(aPos)); |
206 |
241 |
207 const TUint startPos = iCurrentPos.iPos; |
242 const TUint startPos = iCurrentPos.iPos; |
208 const TUint curSize = (TUint)Size(); |
243 const TUint curSize = FCB_FileSize(); |
209 const TUint length = (TUint)aLength; |
244 const TUint length = (TUint)aLength; |
210 |
245 |
211 if((startPos + length > curSize) || (startPos > startPos + length) ) |
246 if((startPos + length > curSize) || (startPos > startPos + length) ) |
212 aLength=curSize-startPos; |
247 aLength=curSize-startPos; |
213 |
248 |
220 { |
255 { |
221 ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0); |
256 ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0); |
222 } |
257 } |
223 |
258 |
224 //----------------------------------------------------------------------------- |
259 //----------------------------------------------------------------------------- |
225 // from CFileCB::MExtendedFileInterface |
260 /** |
|
261 Write data to the file. |
|
262 |
|
263 @param aFilePos start write position within a file |
|
264 @param aLength how many bytes to write; on return contain amount of data actually written |
|
265 @param aDes local buffer desctriptor |
|
266 @param aMessage from file server, used to write data to the media from different address space. |
|
267 @param aDesOffset offset within data descriptor |
|
268 |
|
269 @leave on media read error |
|
270 |
|
271 */ |
226 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset) |
272 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset) |
227 { |
273 { |
228 __PRINT2(_L("CFatFileCB::WriteL aFilePos=%LU aLength=%d"),aPos,aLength); |
274 __PRINT3(_L("CFatFileCB::WriteL[0x%x] pos=%LU len=%d"), this, aPos, aLength); |
|
275 |
229 // FAT supports 32 bits only for file size |
276 // FAT supports 32 bits only for file size |
230 TUint64 endPos = aPos + aLength; |
277 TUint64 endPos = aPos + aLength; |
231 if(endPos > KMaxSupportedFatFileSize) |
278 if(endPos > KMaxSupportedFatFileSize) |
232 User::Leave(KErrNotSupported); |
279 User::Leave(KErrNotSupported); |
233 |
280 |
234 FatMount().CheckStateConsistentL(); |
281 FatMount().CheckStateConsistentL(); |
235 FatMount().CheckWritableL(); |
282 FatMount().CheckWritableL(); |
236 const TUint pos = I64LOW(aPos); |
283 const TUint pos = I64LOW(aPos); |
237 CheckPosL(pos); |
284 CheckPosL(pos); |
238 |
285 |
239 const TUint startCluster = (TUint)iStartCluster; |
286 const TUint startCluster = FCB_StartCluster(); |
240 const TUint length = (TUint)aLength; |
287 const TUint length = (TUint)aLength; |
241 |
288 |
242 endPos = iCurrentPos.iPos + length; |
289 endPos = iCurrentPos.iPos + length; |
243 if ((endPos > (TUint)Size()) || |
290 if ((endPos > FCB_FileSize()) || |
244 (iCurrentPos.iPos > endPos) ) // Overflow condition |
291 (iCurrentPos.iPos > endPos) ) // Overflow condition |
245 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
292 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
246 |
293 |
247 TUint startPos=iCurrentPos.iPos; |
294 TUint startPos=iCurrentPos.iPos; |
248 TInt badcluster=0; |
295 TUint badcluster=0; |
249 TInt goodcluster=0; |
296 TUint goodcluster=0; |
250 |
297 |
251 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster)); |
298 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster)); |
252 |
299 |
253 if (ret == KErrCorrupt || ret == KErrDied) |
300 if (ret == KErrCorrupt || ret == KErrDied) |
254 { |
301 { |
255 if(startCluster == 0) |
302 if(startCluster == 0) |
256 { //Empty File, revert all the clusters allocated. |
303 { //Empty File, revert all the clusters allocated. |
257 TInt cluster = iStartCluster; |
304 const TUint32 cluster = FCB_StartCluster(); |
258 iStartCluster = 0; |
305 FCB_SetStartCluster(0); |
259 SetSize(0); |
306 FCB_SetFileSize(0); |
|
307 IndicateFileSizeModified(ETrue); |
|
308 |
260 FlushAllL(); |
309 FlushAllL(); |
261 |
310 |
262 iCurrentPos.iCluster = 0; |
311 iCurrentPos.iCluster = 0; |
263 iCurrentPos.iPos = 0; |
312 iCurrentPos.iPos = 0; |
264 |
313 |
265 FAT().FreeClusterListL(cluster); |
314 FAT().FreeClusterListL(cluster); |
266 FAT().FlushL(); |
315 FAT().FlushL(); |
267 } |
316 } |
268 else |
317 else |
269 { //Calculate the clusters required based on file size, revert extra clusters if allocated. |
318 { //Calculate the clusters required based on file size, revert extra clusters if allocated. |
270 const TUint curSize = (TUint)Size(); |
319 const TUint curSize = FCB_FileSize(); |
271 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
320 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
272 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
321 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
273 { |
322 { |
274 ClustersNeeded++; |
323 ClustersNeeded++; |
275 } |
324 } |
276 |
325 |
277 TInt cluster = iStartCluster; |
326 TUint32 cluster = FCB_StartCluster(); |
278 while(--ClustersNeeded) |
327 while(--ClustersNeeded) |
279 { |
328 { |
280 FAT().GetNextClusterL(cluster); |
329 FAT().GetNextClusterL(cluster); |
281 } |
330 } |
282 |
331 |
439 } |
488 } |
440 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
489 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
441 } |
490 } |
442 |
491 |
443 //----------------------------------------------------------------------------- |
492 //----------------------------------------------------------------------------- |
444 |
493 /** |
|
494 Set file size. |
|
495 @param aSize new file size. |
|
496 */ |
445 void CFatFileCB::SetSizeL(TInt64 aSize) |
497 void CFatFileCB::SetSizeL(TInt64 aSize) |
446 { |
498 { |
447 __PRINT(_L("CFatFileCB::SetSizeL")); |
499 __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize); |
448 |
500 |
449 // FAT supports 32 bits only for file size |
501 //-- max. file size for FAT is 4GB-1 |
450 if (I64HIGH(aSize)) |
502 if (I64HIGH(aSize)) |
451 User::Leave(KErrNotSupported); |
503 User::Leave(KErrNotSupported); |
452 |
504 |
453 if(FatMount().IsRuggedFSys()) |
505 DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys()); |
454 DoSetSizeL(I64LOW(aSize),ETrue); |
506 } |
|
507 |
|
508 |
|
509 void CFatFileCB::SetSizeL(TInt aSize) |
|
510 { |
|
511 SetSizeL(TInt64(aSize)); |
|
512 } |
|
513 |
|
514 //----------------------------------------------------------------------------- |
|
515 /** |
|
516 Shrink file to zero size. |
|
517 */ |
|
518 void CFatFileCB::DoShrinkFileToZeroSizeL() |
|
519 { |
|
520 ASSERT(FCB_FileSize()); |
|
521 ASSERT(FileSizeModified()); |
|
522 |
|
523 ClearIndex(0); //-- clear seek index array |
|
524 |
|
525 //-- update file dir. entry |
|
526 const TUint32 cluster = FCB_StartCluster(); |
|
527 FCB_SetStartCluster(0); |
|
528 FCB_SetFileSize(0); |
|
529 FlushAllL(); |
|
530 |
|
531 //-- free cluster list. |
|
532 CheckPosL(0); |
|
533 FAT().FreeClusterListL(cluster); |
|
534 FAT().FlushL(); |
|
535 } |
|
536 |
|
537 //----------------------------------------------------------------------------- |
|
538 /* |
|
539 Shrink file to smaller size, but > 0 |
|
540 |
|
541 @param aNewSize new file size |
|
542 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
|
543 */ |
|
544 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
|
545 { |
|
546 ASSERT(FileSizeModified()); |
|
547 ASSERT(FCB_FileSize() > aNewSize && aNewSize); |
|
548 |
|
549 if(aForceCachesFlush) |
|
550 WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry |
|
551 |
|
552 CheckPosL(aNewSize); |
|
553 |
|
554 TUint32 cluster=iCurrentPos.iCluster; |
|
555 if (FAT().GetNextClusterL(cluster)) |
|
556 {//-- truncate the cluster chain |
|
557 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
|
558 FAT().FreeClusterListL(cluster); |
|
559 } |
|
560 |
|
561 ClearIndex(aNewSize); |
|
562 FAT().FlushL(); |
|
563 } |
|
564 |
|
565 //----------------------------------------------------------------------------- |
|
566 /** |
|
567 Expand a file. |
|
568 |
|
569 @param aNewSize new file size. |
|
570 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
|
571 */ |
|
572 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
|
573 { |
|
574 ASSERT(FCB_FileSize() < aNewSize); |
|
575 ASSERT(FileSizeModified()); |
|
576 |
|
577 const TUint32 KClusterSzLog2 = ClusterSizeLog2(); |
|
578 const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
|
579 |
|
580 |
|
581 //-- expanding a file |
|
582 if (FCB_StartCluster() == 0) |
|
583 {//-- the initial file size is 0 (no cluster chain) |
|
584 |
|
585 ClearIndex(0); //-- clear seek index array |
|
586 //-- FAT().FreeClusterHint() will give us a hint of the last free cluster |
|
587 const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); |
|
588 FAT().FlushL(); |
|
589 |
|
590 iCurrentPos.iCluster=tempStartCluster; |
|
591 FCB_SetStartCluster(tempStartCluster); |
|
592 FCB_SetFileSize(aNewSize); |
|
593 FlushAllL(); |
|
594 } |
455 else |
595 else |
456 DoSetSizeL(I64LOW(aSize),EFalse); |
596 { |
457 } |
597 const TUint curSize = FCB_FileSize(); |
458 |
598 const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
459 |
599 ASSERT(newSizeClusters >= oldSizeClusters); |
460 void CFatFileCB::SetSizeL(TInt aSize) |
600 const TUint newClusters = newSizeClusters-oldSizeClusters; //-- Number of clusters we need to append to the existing cluster chain |
461 // |
601 if (newClusters) |
462 // Envelope function around DoSetSizeL to enable aSize to |
602 { |
463 // be written to disk for rugged fat file system |
603 TEntryPos currentPos=iCurrentPos; |
464 // |
604 CheckPosL(FCB_FileSize()); |
465 { |
605 FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); |
466 SetSizeL(TInt64(aSize)); |
606 iCurrentPos=currentPos; |
467 } |
607 } |
468 |
608 |
469 void CFatFileCB::DoSetSizeL(TUint aSize,TBool aIsSizeWrite) |
609 FAT().FlushL(); |
470 // |
610 |
471 // Extend or truncate the file. |
611 if(aForceCachesFlush) // write file size if increasing |
472 // Expects the modified attribute and iSize are set afterwards. |
612 WriteFileSizeL(aNewSize); |
473 // Does not alter iCurrentPos, the current file position. |
613 } |
474 // Writes size of file to disk if aIsSizeWrite set |
614 |
475 // |
615 } |
476 { |
616 |
477 __PRINT2(_L("CFatFileCB::DoSetSizeL sz:%d, fileWrite=%d"),aSize ,aIsSizeWrite); |
617 //----------------------------------------------------------------------------- |
|
618 /** |
|
619 Set file size. This can involve extending/truncating file's cluster chain. |
|
620 @param aSize new file size |
|
621 @param aForceCachesFlush if ETrue, all changes in metadata will go to the media immediately. |
|
622 it is used in Rugged FAT mode. |
|
623 */ |
|
624 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush) |
|
625 { |
|
626 __PRINT4(_L("CFatFileCB::DoSetSizeL[0x%x] sz:%d, oldSz:%d, flush:%d"), this, aSize, FCB_FileSize(), aForceCachesFlush); |
478 |
627 |
479 FatMount().CheckStateConsistentL(); |
628 FatMount().CheckStateConsistentL(); |
480 FatMount().CheckWritableL(); |
629 FatMount().CheckWritableL(); |
481 |
630 |
482 |
631 |
483 // Can not change the file size if it is clamped |
632 // Can not change the file size if it is clamped |
484 if(Mount().IsFileClamped(MAKE_TINT64(0,iStartCluster)) > 0) |
633 if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0) |
485 User::Leave(KErrInUse); |
634 User::Leave(KErrInUse); |
486 |
635 |
487 iFileSizeModified=ETrue; |
636 if(aSize == FCB_FileSize()) |
|
637 return; |
|
638 |
|
639 IndicateFileSizeModified(ETrue); |
488 |
640 |
489 TInt newIndexMult=CalcSeekIndexSize(aSize); |
641 TInt newIndexMult=CalcSeekIndexSize(aSize); |
490 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
642 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
491 ResizeIndex(newIndexMult,aSize); |
643 ResizeIndex(newIndexMult,aSize); |
492 if (aSize == 0) |
644 |
493 { |
645 //------------------------------------------- |
494 if (Size() != 0) |
646 //-- shrinking file to 0 size |
495 { |
647 if(aSize == 0) |
496 ClearIndex(0); //-- clear seek index array |
648 { |
497 TInt cluster=iStartCluster; |
649 DoShrinkFileToZeroSizeL(); |
498 iStartCluster = 0; |
650 return; |
499 SetSize(0); |
651 } |
500 FlushAllL(); |
652 |
501 CheckPosL(0); |
653 //------------------------------------------- |
502 FAT().FreeClusterListL(cluster); |
654 //-- shrinking file to non-zero size |
503 FAT().FlushL(); |
655 if (aSize < FCB_FileSize()) |
504 } |
656 { |
505 return; |
657 DoShrinkFileL(aSize, aForceCachesFlush); |
506 } |
658 return; |
507 if (aSize<(TUint)Size()) |
659 } |
508 { |
660 |
509 if(aIsSizeWrite) // write file size if decreasing |
661 //------------------------------------------- |
510 WriteFileSizeL(aSize); |
662 //-- expanding a file |
511 CheckPosL(aSize); |
663 DoExpandFileL(aSize, aForceCachesFlush); |
512 TInt cluster=iCurrentPos.iCluster; |
664 |
513 if (FAT().GetNextClusterL(cluster)) |
665 } |
514 { |
666 |
515 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
667 //----------------------------------------------------------------------------- |
516 FAT().FreeClusterListL(cluster); |
668 /** |
517 } |
669 Set file entry details, like file attributes and modified time |
518 ClearIndex(aSize); |
670 This method doesn't write data to the media immediately, instead, all modified data are cached and can be flushed later |
519 FAT().FlushL(); |
671 in FlushAllL() |
520 return; |
672 |
521 } |
673 @param aTime file modification time (and last access as well) |
522 |
674 @param aSetAttMask file attributes OR mask |
523 TUint newSize=aSize>>ClusterSizeLog2(); // Number of clusters we now need |
675 @param aClearAttMask file attributes AND mask |
524 if (aSize > (newSize<<ClusterSizeLog2())) |
676 |
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 */ |
677 */ |
564 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
678 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
565 { |
679 { |
566 __PRINT(_L("CFatFileCB::SetEntryL")); |
680 __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this); |
567 |
681 |
568 FatMount().CheckStateConsistentL(); |
682 FatMount().CheckStateConsistentL(); |
569 FatMount().CheckWritableL(); |
683 FatMount().CheckWritableL(); |
570 |
684 |
571 TUint setAttMask=aSetAttMask&KEntryAttMaskSupported; |
685 //-- change file attributes |
|
686 const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set |
|
687 TUint newAtt = Att(); |
|
688 |
572 if (setAttMask|aClearAttMask) |
689 if (setAttMask|aClearAttMask) |
573 { |
690 { |
574 iAtt|=setAttMask; |
691 newAtt |= setAttMask; |
575 iAtt&=(~aClearAttMask); |
692 newAtt &= ~aClearAttMask; |
576 } |
693 SetAtt(newAtt); |
|
694 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
|
695 } |
|
696 |
|
697 //-- set file entry modification time if required |
577 if (aSetAttMask&KEntryAttModified) |
698 if (aSetAttMask&KEntryAttModified) |
578 iModified=aTime; |
699 { |
579 iAtt|=KEntryAttModified; |
700 SetModified(aTime); //-- set file modified time |
580 } |
701 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
581 |
702 IndicateFileTimeModified(ETrue); //-- this will force writing file mod. time to the media on Flush |
582 /** |
703 } |
583 This is a RuggedFAT - specific method. Writes file size to the corresponding field of this |
704 |
584 file direcrory entry. |
705 } |
585 */ |
706 |
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 |
707 |
598 //----------------------------------------------------------------------------- |
708 //----------------------------------------------------------------------------- |
599 /** |
709 /** |
600 Flush file size, attributes, time etc. to the media. |
710 The same as FlushAllL(). This method is called from RFile::Flush() |
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 */ |
711 */ |
604 void CFatFileCB::FlushDataL() |
712 void CFatFileCB::FlushDataL() |
605 { |
713 { |
606 __PRINT(_L("CFatFileCB::FlushDataL")); |
714 __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this); |
607 FlushAllL(); |
715 FlushAllL(); |
608 } |
716 } |
609 |
717 |
610 //----------------------------------------------------------------------------- |
718 //----------------------------------------------------------------------------- |
611 /** |
719 /** |
612 Flush the fide directory entry data: files size, attributes, time etc. |
720 Flush the fide directory entry data: files size, attributes, time etc. |
613 */ |
721 */ |
614 void CFatFileCB::FlushAllL() |
722 void CFatFileCB::FlushAllL() |
615 { |
723 { |
616 __PRINT(_L("CFatFileCB::FlushAllL()")); |
724 |
|
725 //-- define this symbol in order to enable legacy behaviour, i.e. compulsory updating file dir. entry on flush. |
|
726 //-- otherwise the FlushAllL() will update the file dir. entry only if it differs from what is on the media, i.e. |
|
727 //-- file size, start cluster, attributes and modification timestamp |
|
728 #define ALWAYS_UPDATE_ENTRY_ON_FLUSH |
|
729 |
|
730 __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this); |
617 |
731 |
618 if (Mount().IsCurrentMount()==EFalse) |
732 if (Mount().IsCurrentMount()==EFalse) |
619 User::Leave(KErrDisMounted); |
733 User::Leave(KErrDisMounted); |
620 |
734 |
621 FatMount().CheckStateConsistentL(); |
735 FatMount().CheckStateConsistentL(); |
622 FatMount().CheckWritableL(); |
736 FatMount().CheckWritableL(); |
623 |
737 |
|
738 if(!FileSizeModified() && !FileAttModified() && !FileTimeModified()) |
|
739 return; //-- nothing has changed in the file entry at all |
|
740 |
|
741 |
|
742 //-- read file dir. entry |
624 TFatDirEntry entry; |
743 TFatDirEntry entry; |
625 FatMount().ReadDirEntryL(iFileDirPos,entry); |
744 FatMount().ReadDirEntryL(iFileDosEntryPos,entry); |
626 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
745 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
627 entry.SetAttributes(iAtt&KEntryAttMaskSupported); |
746 |
628 entry.SetSize(Size()); |
747 //-- the problem with KEntryAttModified here is that the file server uses this flag to |
629 entry.SetTime(iModified, FatMount().TimeOffset()); |
748 //-- deal with dirty file data. This means that this flag can be set even if there were no changes |
630 entry.SetStartCluster(iStartCluster); |
749 //-- in file time and attributes. Just check if any of the entry field has changed at all |
631 |
750 |
632 TBool setNotify = FatMount().GetNotifyUser(); |
751 TBool bUpdateDirEntry = ETrue; |
|
752 const TTimeIntervalSeconds timeOffset = FatMount().TimeOffset(); |
|
753 |
|
754 #ifndef ALWAYS_UPDATE_ENTRY_ON_FLUSH |
|
755 |
|
756 TBool bTimeModified = FileTimeModified(); //-- check if file modifiication time has been changed explicitly |
|
757 if(bTimeModified) |
|
758 {//-- additional check; for FAT entry modification time has 2 sec. granularity. |
|
759 bTimeModified = !entry.IsTimeTheSame(iModified, timeOffset); |
|
760 } |
|
761 |
|
762 if(!bTimeModified) |
|
763 if(//-- TS is the same as on the media, check other entry fields |
|
764 (entry.Attributes() == (Att() & KEntryAttMaskSupported)) && //-- file attributes have not changed |
|
765 (entry.Size() == FCB_FileSize()) && //-- file size hasn't changed |
|
766 (entry.StartCluster() == FCB_StartCluster()) //-- file start cluster hasn't changed |
|
767 ) |
|
768 { |
|
769 bUpdateDirEntry = EFalse; //-- no need to update file dir. entry |
|
770 } |
|
771 |
|
772 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH |
|
773 |
|
774 if(bUpdateDirEntry) |
|
775 {//-- write entry to the media |
|
776 __PRINT(_L(" CFatFileCB::FlushAllL #1")); |
|
777 entry.SetAttributes(Att() & KEntryAttMaskSupported); |
|
778 entry.SetSize(FCB_FileSize()); |
|
779 entry.SetTime(iModified, timeOffset); |
|
780 |
|
781 entry.SetStartCluster(FCB_StartCluster()); |
|
782 |
|
783 const TBool setNotify = FatMount().GetNotifyUser(); |
633 if(setNotify) |
784 if(setNotify) |
634 { |
785 { |
635 FatMount().SetNotifyOff(); // do not launch a notifier |
786 FatMount().SetNotifyOff(); // do not launch a notifier |
636 } |
787 } |
637 |
788 |
638 TRAPD(ret, FatMount().WriteDirEntryL(iFileDirPos,entry)); |
789 TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry)); |
639 |
790 |
640 if(setNotify) |
791 if(setNotify) |
641 { |
792 { |
642 FatMount().SetNotifyOn(); |
793 FatMount().SetNotifyOn(); |
643 } |
794 } |
644 |
795 |
645 User::LeaveIfError(ret); |
796 User::LeaveIfError(ret); |
646 iAtt&=(~KEntryAttModified); |
797 |
647 iFileSizeModified=EFalse; |
798 IndicateFileSizeModified(EFalse); |
|
799 IndicateFileTimeModified(EFalse); |
|
800 } |
|
801 |
|
802 |
|
803 //-- KEntryAttModified must be reset anyway |
|
804 IndicateFileAttModified(EFalse); |
648 } |
805 } |
649 |
806 |
650 //----------------------------------------------------------------------------- |
807 //----------------------------------------------------------------------------- |
651 |
808 |
652 /** |
809 /** |