79 |
79 |
80 |
80 |
81 CFatMountCB::CFatMountCB() |
81 CFatMountCB::CFatMountCB() |
82 { |
82 { |
83 __PRINT2(_L("CFatMountCB::CFatMountCB() 0x%x, %S"), this, &KThisFsyName); |
83 __PRINT2(_L("CFatMountCB::CFatMountCB() 0x%x, %S"), this, &KThisFsyName); |
84 iFatType = EInvalid; |
84 |
|
85 SetFatType(EInvalid); |
85 iState = ENotMounted; |
86 iState = ENotMounted; |
|
87 |
86 DBG_STATEMENT(iCBRecFlag = 0); //-- debug flag only |
88 DBG_STATEMENT(iCBRecFlag = 0); //-- debug flag only |
87 } |
89 } |
88 |
90 |
89 CFatMountCB::~CFatMountCB() |
91 CFatMountCB::~CFatMountCB() |
90 { |
92 { |
230 //------------------------------------------------------------------------------------------------------------------- |
232 //------------------------------------------------------------------------------------------------------------------- |
231 |
233 |
232 /** |
234 /** |
233 Try remount this Fat volume. Checks if the volume parameters remained the same as on original MountL() call, and |
235 Try remount this Fat volume. Checks if the volume parameters remained the same as on original MountL() call, and |
234 if they are, re-initialises the mount. This includes resetting all caches. |
236 if they are, re-initialises the mount. This includes resetting all caches. |
235 ! Do not call this method from TFatDriveInterface methods, like citical and non-critical notifiers ! This can lead to the |
237 ! Do not call this method from TDriveInterface methods, like citical and non-critical notifiers ! This can lead to the |
236 recursive loops and undefined behaviour. |
238 recursive loops and undefined behaviour. |
237 |
239 |
238 @return KErrNone if the remount was OK |
240 @return KErrNone if the remount was OK |
239 system-wide error code otherwise |
241 system-wide error code otherwise |
240 */ |
242 */ |
435 |
437 |
436 //------------------------------------------------------------------------------------------------------------------- |
438 //------------------------------------------------------------------------------------------------------------------- |
437 |
439 |
438 /** |
440 /** |
439 Open CFatMountCB for write. I.e. perform some actions on the first write attempt. |
441 Open CFatMountCB for write. I.e. perform some actions on the first write attempt. |
440 This is a callback from TFatDriveInterface. |
442 This is a callback from TDriveInterface. |
441 @return System wide error code. |
443 @return System wide error code. |
442 */ |
444 */ |
443 TInt CFatMountCB::OpenMountForWrite() |
445 TInt CFatMountCB::OpenMountForWrite() |
444 { |
446 { |
445 if(State() == EInit_W) |
447 if(State() == EInit_W) |
448 __PRINT1(_L("#- CFatMountCB::OpenMountForWrite() drv:%d\n"),DriveNumber()); |
450 __PRINT1(_L("#- CFatMountCB::OpenMountForWrite() drv:%d\n"),DriveNumber()); |
449 |
451 |
450 ASSERT(State() == EInit_R || State() == EFinalised); |
452 ASSERT(State() == EInit_R || State() == EFinalised); |
451 |
453 |
452 //-- Check possible recursion. This method must not be called recursively. SetVolumeCleanL() works through direct disc access and |
454 //-- Check possible recursion. This method must not be called recursively. SetVolumeCleanL() works through direct disc access and |
453 //-- can not call TFatDriveInterface methods that call this method etc. |
455 //-- can not call TDriveInterface methods that call this method etc. |
454 ASSERT(iCBRecFlag == 0); |
456 ASSERT(iCBRecFlag == 0); |
455 DBG_STATEMENT(iCBRecFlag = 1); //-- set recursion check flag |
457 DBG_STATEMENT(iCBRecFlag = 1); //-- set recursion check flag |
456 |
458 |
457 //-- do here some "opening" work, like marking volme as dirty |
459 //-- do here some "opening" work, like marking volme as dirty |
458 //-- be careful here, as soon as this is a callback from TFatDriveInterface, writing via TFatDriveInterface may cause some unwanted recursion. |
460 //-- be careful here, as soon as this is a callback from TDriveInterface, writing via TDriveInterface may cause some unwanted recursion. |
459 |
461 |
460 //-- mark the volume as dirty |
462 //-- mark the volume as dirty |
461 TInt nRes=KErrNone; |
463 TInt nRes=KErrNone; |
462 TRAP(nRes, SetVolumeCleanL(EFalse)); |
464 TRAP(nRes, SetVolumeCleanL(EFalse)); |
463 if(nRes == KErrNone) |
465 if(nRes == KErrNone) |
2249 |
2251 |
2250 const TInt64 mruPos = MakeLinAddrL(aDosEntryPos); |
2252 const TInt64 mruPos = MakeLinAddrL(aDosEntryPos); |
2251 |
2253 |
2252 pDirCache->MakePageMRU(mruPos); |
2254 pDirCache->MakePageMRU(mruPos); |
2253 |
2255 |
2254 // only update the leaf dir cache when the original cache index is provided |
2256 //-- if the corresponding leaf directory name is cached, associate the last search positionin this directory. |
|
2257 //-- the next search in this dir. will start from this position (and will wrap around over the dir. beginning). |
|
2258 //-- the "last search position" will is the position of current VFAT entryset start. |
2255 if (aLeafDir.iClusterNum) |
2259 if (aLeafDir.iClusterNum) |
2256 { |
2260 { |
2257 iLeafDirCache->UpdateMRUPos(TLeafDirData(aLeafDir.iClusterNum, aStartEntryPos)); |
2261 iLeafDirCache->UpdateMRUPos(TLeafDirData(aLeafDir.iClusterNum, aStartEntryPos)); |
2258 } |
2262 } |
2259 } |
2263 } |
2275 return; |
2279 return; |
2276 |
2280 |
2277 TInt count = 1; |
2281 TInt count = 1; |
2278 |
2282 |
2279 iTargetName.Set(aTargetName); |
2283 iTargetName.Set(aTargetName); |
2280 isLegalDosName = IsLegalDosName(aTargetName, ETrue, EFalse, EFalse, ETrue, EFalse); |
2284 isLegalDosName = IsLegalDosName(aTargetName, ETrue, EFalse, EFalse, ETrue, EFalse); |
2281 |
2285 |
2282 if(isLegalDosName) |
2286 if(isLegalDosName) |
2283 {//-- iShortName will contain generated short DOS name by long filename |
2287 {//-- iShortName will contain generated short DOS name by long filename |
2284 iShortName = DoGenerateShortNameL(aTargetName, count, ETrue); |
2288 iShortName = DoGenerateShortNameL(aTargetName, count, ETrue); |
2285 } |
2289 } |
2499 //--------------------------------------------------- |
2503 //--------------------------------------------------- |
2500 //-- if we have fully specified name and directory cache is present, try to |
2504 //-- if we have fully specified name and directory cache is present, try to |
2501 //-- locate the name in the cache first to avoid reading from media |
2505 //-- locate the name in the cache first to avoid reading from media |
2502 //-- if the entry belongs to the root directory (for FAT12,16) skip the lookup, because root directory isn't aligned by cluster size boundary, |
2506 //-- if the entry belongs to the root directory (for FAT12,16) skip the lookup, because root directory isn't aligned by cluster size boundary, |
2503 //-- while directory cache pages are. For FAT32 it doesn't matter, because root dir is a usual file. |
2507 //-- while directory cache pages are. For FAT32 it doesn't matter, because root dir is a usual file. |
|
2508 |
|
2509 //-- the "rummage dir. cache" can be swithed off. This is not affecting the functionality, only the performance. |
|
2510 #if 1 |
2504 if(iRawDisk->DirCacheInterface() && trgNameFullySpecified && !IsRootDir(aDosEntryPos) && !aFileCreationHelper) |
2511 if(iRawDisk->DirCacheInterface() && trgNameFullySpecified && !IsRootDir(aDosEntryPos) && !aFileCreationHelper) |
2505 {//-- aName is fully specified, i.e doesn't contain wildcards |
2512 {//-- aName is fully specified, i.e doesn't contain wildcards |
2506 |
2513 |
2507 findHelper.InitialiseL(trgtNameNoDot); |
2514 findHelper.InitialiseL(trgtNameNoDot); |
2508 |
2515 |
2510 if(bMatchFound) |
2517 if(bMatchFound) |
2511 { |
2518 { |
2512 return(aStartEntry.IsVFatEntry()); |
2519 return(aStartEntry.IsVFatEntry()); |
2513 } |
2520 } |
2514 } |
2521 } |
|
2522 #endif |
|
2523 |
2515 //--------------------------------------------------- |
2524 //--------------------------------------------------- |
2516 |
2525 |
2517 // we need to scan ahead from the mru pos then come back to beginning, if startcluster is provided |
2526 // we need to scan ahead from the mru pos then come back to beginning, if startcluster is provided |
2518 TBool scanAhead = EFalse; |
2527 TBool scanAhead = EFalse; |
2519 // if we have a starting cluster number (and it's not root directory in FAT16/12 case)&& |
2528 // if we have a starting cluster number (and it's not root directory in FAT16/12 case)&& |
2653 if(findHelper.MatchDosEntryName(aDosEntry.Name().Ptr())) |
2662 if(findHelper.MatchDosEntryName(aDosEntry.Name().Ptr())) |
2654 { |
2663 { |
2655 found = ETrue; |
2664 found = ETrue; |
2656 break; //-- DOS entries match, success. |
2665 break; //-- DOS entries match, success. |
2657 } |
2666 } |
|
2667 |
2658 } |
2668 } |
2659 else if (!trgNameFullySpecified) |
2669 else if (!trgNameFullySpecified) |
2660 {//-- target name contains wildcards, we need to use MatchF with dos name |
2670 {//-- target name contains wildcards, we need to use MatchF with dos name |
2661 TBuf8<0x20> dosName8(DosNameFromStdFormat(aDosEntry.Name())); |
2671 TBuf8<0x20> dosName8(DosNameFromStdFormat(aDosEntry.Name())); |
2662 TBuf<0x20> dosName; |
2672 TBuf<0x20> dosName; |
2663 LocaleUtils::ConvertToUnicodeL(dosName, dosName8); //-- convert DOS name to unicode (implies locale settings) |
2673 LocaleUtils::ConvertToUnicodeL(dosName, dosName8); //-- convert DOS name to unicode (implies locale settings) |
2664 if (dosName.MatchF(trgtNameNoDot)!=KErrNotFound) |
2674 if (dosName.MatchF(trgtNameNoDot)!=KErrNotFound) |
2665 { |
2675 { |
2666 found = ETrue; |
2676 found = ETrue; |
2667 break; |
2677 break; |
2668 } |
2678 } |
2669 } |
2679 } |
2670 |
2680 |
2671 |
2681 |
2672 } |
2682 } |
2673 else //if (aStartEntry.IsVFatEntry()) |
2683 else //if (aStartEntry.IsVFatEntry()) |
2674 {//-- we've read a legacy FAT entry, so compare DOS entries |
2684 {//-- we've read a legacy FAT entry, so compare DOS entries |
2761 if (iRawDisk->DirCacheInterface() && aDosEntryPos.Cluster()) |
2771 if (iRawDisk->DirCacheInterface() && aDosEntryPos.Cluster()) |
2762 { |
2772 { |
2763 TInt64 mruPos = MakeLinAddrL(aDosEntryPos); |
2773 TInt64 mruPos = MakeLinAddrL(aDosEntryPos); |
2764 iRawDisk->DirCacheInterface()->MakePageMRU(mruPos); |
2774 iRawDisk->DirCacheInterface()->MakePageMRU(mruPos); |
2765 |
2775 |
2766 // only update the leaf dir cache when the original cache index is provided |
2776 //-- if the corresponding leaf directory name is cached, associate the last search positionin this directory. |
2767 if (aLeafDirData.iClusterNum) |
2777 //-- the next search in this dir. will start from this position (and will wrap around over the dir. beginning). |
|
2778 //-- the "last search position" will is the position of current VFAT entryset start. |
|
2779 if(aLeafDirData.iClusterNum) |
2768 { |
2780 { |
2769 iLeafDirCache->UpdateMRUPos(TLeafDirData(aLeafDirData.iClusterNum, aDosEntryPos)); |
2781 iLeafDirCache->UpdateMRUPos(TLeafDirData(aLeafDirData.iClusterNum, aStartEntryPos)); |
2770 } |
2782 } |
2771 } |
2783 } |
2772 |
2784 |
2773 return (aStartEntry.IsVFatEntry()); |
2785 return (aStartEntry.IsVFatEntry()); |
2774 } |
2786 } |
4300 // cluster count may be zero if boot sector failed to be read (e.g. if the media is locked) |
4312 // cluster count may be zero if boot sector failed to be read (e.g. if the media is locked) |
4301 // or if TDrive::MountMedia(ETrue) has been called (in which case the boot sector may |
4313 // or if TDrive::MountMedia(ETrue) has been called (in which case the boot sector may |
4302 if (MaxClusters == 0) |
4314 if (MaxClusters == 0) |
4303 return KErrCorrupt; |
4315 return KErrCorrupt; |
4304 |
4316 |
|
4317 //-- used for measuring time |
|
4318 TTime timeStart; |
|
4319 TTime timeEnd; |
|
4320 timeStart.UniversalTime(); //-- take start time |
|
4321 |
|
4322 |
4305 RBitVector bitVec; //-- each bit in this vector represents a FAT cluster |
4323 RBitVector bitVec; //-- each bit in this vector represents a FAT cluster |
4306 |
4324 |
4307 TInt nRes = bitVec.Create(MaxClusters); |
4325 TInt nRes = bitVec.Create(MaxClusters); |
4308 if(nRes != KErrNone) |
4326 if(nRes != KErrNone) |
4309 { |
4327 { |
4560 DismountedLocalDrive(); |
4585 DismountedLocalDrive(); |
4561 |
4586 |
4562 return nRes; |
4587 return nRes; |
4563 } |
4588 } |
4564 |
4589 |
4565 |
4590 //----------------------------------------------------------------------------------------- |
4566 |
4591 /** |
|
4592 Internal helper method. |
|
4593 @param aFatType FAT type |
|
4594 @return End Of Cluster Chain code that depend on FAT type, 0xff8 for FAT12, 0xfff8 for FAT16, and 0xffffff8 for FAT32 |
|
4595 */ |
|
4596 TUint32 EocCodeByFatType(TFatType aFatType) |
|
4597 { |
|
4598 switch(aFatType) |
|
4599 { |
|
4600 case EFat32: |
|
4601 return EOF_32Bit-7; //-- 0xffffff8 |
|
4602 |
|
4603 case EFat16: |
|
4604 return EOF_16Bit-7; //-- 0xfff8 |
|
4605 |
|
4606 case EFat12: |
|
4607 return EOF_12Bit-7; //-- 0xff8 |
|
4608 |
|
4609 default: |
|
4610 ASSERT(aFatType == EInvalid); |
|
4611 return 0; |
|
4612 } |
|
4613 |
|
4614 } |
|
4615 |
|
4616 //----------------------------------------------------------------------------------------- |
|
4617 /** |
|
4618 Set FAT type that this object of CFatMountCB will be dealing with. |
|
4619 */ |
|
4620 void CFatMountCB::SetFatType(TFatType aFatType) |
|
4621 { |
|
4622 ASSERT(State() == ENotMounted || State() == EDismounted || State() == EMounting) ; |
|
4623 |
|
4624 iFatType = aFatType; |
|
4625 iFatEocCode = EocCodeByFatType(aFatType); |
|
4626 } |
|
4627 |
|
4628 |
|
4629 |
|
4630 |
|
4631 |
|
4632 |
|
4633 |
|
4634 |
|
4635 |
|
4636 |
|
4637 |
|
4638 |
|
4639 |
|
4640 |
|
4641 |
|
4642 |
|
4643 |