userlibandfileserver/fileserver/sfat32/sl_mnt.cpp
changeset 33 0173bcd7697c
parent 15 4122176ea935
child 36 538db54a451d
equal deleted inserted replaced
31:56f325a607ea 33:0173bcd7697c
    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         {
  4318         TRAP(r,CheckUnvisitedClustersL(bitVec));
  4336         TRAP(r,CheckUnvisitedClustersL(bitVec));
  4319         }
  4337         }
  4320 
  4338 
  4321 
  4339 
  4322     bitVec.Close();
  4340     bitVec.Close();
       
  4341 
       
  4342     timeEnd.UniversalTime(); //-- take end time
       
  4343     const TInt msScanTime = (TInt)( (timeEnd.MicroSecondsFrom(timeStart)).Int64() / K1mSec);
       
  4344     (void)msScanTime;
       
  4345 
       
  4346     __PRINT1(_L("#@@@ CheckDisk() time taken:%d ms"), msScanTime);
       
  4347 
  4323 
  4348 
  4324     switch(r)
  4349     switch(r)
  4325         {
  4350         {
  4326 
  4351 
  4327     case KErrNone:
  4352     case KErrNone:
  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