userlibandfileserver/fileserver/sfat32/sl_mnt32.cpp
changeset 43 96e5fb8b040d
child 33 0173bcd7697c
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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\sfat32\sl_mnt32.cpp
       
    15 // CFatMountCB code, specific to the EFAT32.FSY
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file 
       
    21 */
       
    22 
       
    23 #include "sl_std.h"
       
    24 #include "sl_cache.h"
       
    25 #include "sl_leafdir_cache.h"
       
    26 
       
    27 //-------------------------------------------------------------------------------------------------------------------
       
    28 
       
    29 
       
    30 /**
       
    31     Write aligned members of TFatBootSector to media
       
    32  
       
    33     @param  aMediaPos   media position the data will be written to
       
    34     @param  aBootSector data to write
       
    35     @return Media write error code
       
    36 */
       
    37 TInt CFatMountCB::DoWriteBootSector(TInt64 aMediaPos, const TFatBootSector& aBootSector)  const
       
    38     {
       
    39     __PRINT2(_L("#- CFatMountCB::DoWriteBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   
       
    40 
       
    41     ASSERT(aMediaPos>=0);
       
    42 
       
    43     TBuf8<KDefaultSectorSize> bootSecBuf(KDefaultSectorSize);
       
    44     bootSecBuf.FillZ();
       
    45 
       
    46     //-- externalize boot sector to the data buffer
       
    47     aBootSector.Externalize(bootSecBuf);
       
    48 
       
    49     //-- put a boot sector signature to the last 2 bytes
       
    50     bootSecBuf[KDefaultSectorSize-2] = 0x55;
       
    51     bootSecBuf[KDefaultSectorSize-1] = 0xaa;
       
    52 
       
    53     //-- write boot sector to the media
       
    54     TInt r=LocalDrive()->Write(aMediaPos, bootSecBuf);
       
    55     if (r!=KErrNone)
       
    56         {//-- write failure
       
    57         __PRINT2(_L("CFatMountCB::DoWriteBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
       
    58         }
       
    59 
       
    60     return r;
       
    61     }
       
    62 
       
    63 //-------------------------------------------------------------------------------------------------------------------
       
    64 
       
    65 /**
       
    66     Read non aligned boot data from media into TFatBootSector structure
       
    67 
       
    68     @param  aMediaPos   media position the data will be read from
       
    69     @param  aBootSector refrence to TFatBootSector populate
       
    70     @return Media read error code
       
    71 */
       
    72 TInt CFatMountCB::DoReadBootSector(TInt64 aMediaPos, TFatBootSector& aBootSector)  const
       
    73     {
       
    74     __PRINT2(_L("#- CFatMountCB::DoReadBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   
       
    75 
       
    76     ASSERT(aMediaPos>=0);
       
    77 
       
    78     TBuf8<KSizeOfFatBootSector> bootSecBuf(KSizeOfFatBootSector);
       
    79     
       
    80     //-- read boot sector from the media
       
    81     TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf);
       
    82     
       
    83     if (r != KErrNone)
       
    84         {
       
    85         __PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
       
    86 
       
    87 	    //-- fiddling with the error code; taken from MountL()
       
    88         if (r==KErrNotSupported)
       
    89 		    return KErrNotReady;
       
    90     #if defined(_LOCKABLE_MEDIA)
       
    91 	    else if(r==KErrLocked)
       
    92 		    return KErrLocked;
       
    93     #endif
       
    94 	    else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
       
    95                 return KErrCorrupt; 
       
    96 
       
    97         return r;
       
    98         }
       
    99 
       
   100     ASSERT(r==KErrNone);
       
   101 
       
   102     //-- initialise TFatBootSector object
       
   103     aBootSector.Internalize(bootSecBuf);
       
   104 
       
   105     //-- Validate the partition size, and fix up if the out of bounds
       
   106     TLocalDriveCapsV2Buf localDriveCaps;
       
   107     r = LocalDrive()->Caps(localDriveCaps);
       
   108     if (r != KErrNone)
       
   109         {
       
   110         //-- fiddling with the error code; taken from MountL()
       
   111         if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
       
   112             return KErrCorrupt;
       
   113         else
       
   114             return r;
       
   115         }
       
   116 
       
   117     if(!(localDriveCaps().iMediaAtt & KMediaAttVariableSize))
       
   118         {//-- this is not a RAM drive.
       
   119         const TUint32 maxSectors = I64LOW(localDriveCaps().iSize >> KDefSectorSzLog2);
       
   120 
       
   121         if(aBootSector.TotalSectors())
       
   122             aBootSector.SetTotalSectors(Min(aBootSector.TotalSectors(), maxSectors));
       
   123         else
       
   124             aBootSector.SetHugeSectors(Min(aBootSector.HugeSectors(), maxSectors));
       
   125         }
       
   126 
       
   127     return KErrNone;
       
   128     }
       
   129 
       
   130 //-------------------------------------------------------------------------------------------------------------------
       
   131 
       
   132 /**
       
   133     Read and validate the boot sector.
       
   134     If there is an error in reading the main boot sector (sec:0) or it is invalid, tries to read backup boot sector from sec:6.
       
   135     Flag iMainBootSecValid indicates the validity of the main boot sector. if it is false, but ret. value is KErrNone, it means that
       
   136     the backup boot sector was used and it is valid.
       
   137 
       
   138     @param      aBootSector reference to the boot sector object to be read.
       
   139     @param      aDoNotReadBkBootSec if true, there won't be an attempt to read backup sector
       
   140     @return     standard error code.
       
   141 
       
   142 */
       
   143 TInt CFatMountCB::ReadBootSector(TFatBootSector& aBootSector, TBool aDoNotReadBkBootSec/*=EFalse*/)
       
   144     {
       
   145     iMainBootSecValid = EFalse; 
       
   146 
       
   147     //-- read main boot sector from the sector 0
       
   148     TInt nRes = DoReadBootSector(KBootSectorNum << KDefSectorSzLog2, aBootSector); 
       
   149     if(nRes == KErrNone)
       
   150         {
       
   151         if(aBootSector.IsValid())
       
   152             {
       
   153             iMainBootSecValid = ETrue; //-- main boot sector is valid, everything is OK
       
   154             return KErrNone;
       
   155             }
       
   156         else
       
   157             {
       
   158             __PRINT(_L("MainBoot Sector is invalid! dump:\n"));
       
   159             aBootSector.PrintDebugInfo();
       
   160             nRes = KErrCorrupt;
       
   161             }
       
   162         }
       
   163 
       
   164     ASSERT(nRes!= KErrNone && !iMainBootSecValid);
       
   165 
       
   166     if(aDoNotReadBkBootSec)
       
   167         return nRes;
       
   168 
       
   169     //-- main boot sector is invalid, try backup one (it might not present at all) 
       
   170     __PRINT(_L("Using backup boot sector...\n"));
       
   171     nRes=DoReadBootSector(KBkBootSectorNum << KDefSectorSzLog2, aBootSector); 
       
   172     if(nRes == KErrNone )
       
   173         {
       
   174         if(aBootSector.IsValid())
       
   175             return KErrNone; //-- main boot sector is bad, but backup one is OK
       
   176         else
       
   177             {//-- backup boot sector is invalid
       
   178             __PRINT(_L("Backup Sector is invalid! dump:\n"));    
       
   179             aBootSector.PrintDebugInfo();
       
   180             nRes = KErrCorrupt;
       
   181             }
       
   182         }
       
   183     
       
   184     //-- can't read boot sectors, or both are invalid
       
   185     return nRes;
       
   186     }
       
   187 
       
   188 //-------------------------------------------------------------------------------------------------------------------
       
   189 
       
   190 /**
       
   191 Write a new volume label to BPB in media
       
   192 
       
   193 @param aVolumeLabel Descriptor containing the new volume label
       
   194 @leave 
       
   195 */
       
   196 void CFatMountCB::WriteVolumeLabelL(const TDesC8& aVolumeLabel) const
       
   197     {
       
   198     if(aVolumeLabel.Length() > KVolumeLabelSize)
       
   199         User::Leave(KErrArgument);
       
   200 
       
   201     const TUint32 posVolLabel = Is32BitFat() ? KFat32VolumeLabelPos : KFat16VolumeLabelPos;
       
   202     User::LeaveIfError(LocalDrive()->Write(posVolLabel, aVolumeLabel)); 
       
   203     
       
   204     }
       
   205 
       
   206 
       
   207 //-------------------------------------------------------------------------------------------------------------------
       
   208 
       
   209 const TUint32 KFat32CleanShutDownMask	= 0x08000000; ///< Mask used to indicate test clean/dirty bit for Fat32
       
   210 const TUint16 KFat16CleanShutDownMask	= 0x08000;    ///< Mask used to indicate test clean/dirty bit for Fat16
       
   211 
       
   212 /**
       
   213 Set or reset "VolumeClean" (ClnShutBitmask) flag.
       
   214 
       
   215 @param  aClean if ETrue, marks the volume as clean, otherwise as dirty.
       
   216 @leave  if write error occured.        
       
   217 */
       
   218 void CFatMountCB::SetVolumeCleanL(TBool aClean) 
       
   219     {
       
   220 
       
   221 	//-- The volume can't be set clean if there are objects opened on it. This precondition must be checked before calling this function
       
   222     if(aClean && LockStatus()!=0)
       
   223         {
       
   224         __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
       
   225         ASSERT(0);
       
   226         User::Leave(KErrInUse);
       
   227         return;
       
   228         }
       
   229     
       
   230     if(FatType() == EFat12)
       
   231         {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive (ignoring any error for now as there's nothing we can do with it)
       
   232 		(void)LocalDrive()->Finalise(aClean);
       
   233         return;
       
   234         }
       
   235 
       
   236     //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. 
       
   237     //-- this is because CFatTable doesn't allow access to FAT[0] & FAT[1]
       
   238     //-- We also need to write data through CProxyDrive, because TFatDriveInterface has a call back that can call this method
       
   239 
       
   240     if(Is32BitFat())
       
   241         {//-- Fat32
       
   242 		__PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT32"),DriveNumber(), aClean);
       
   243 		
       
   244         TFat32Entry fatEntry;
       
   245         const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
       
   246         TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
       
   247         
       
   248         User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT32[1] entry
       
   249 
       
   250         const TFat32Entry tmp = fatEntry;
       
   251         
       
   252         if(aClean)
       
   253             fatEntry |= KFat32CleanShutDownMask;  //-- set ClnShutBit flag
       
   254         else
       
   255             fatEntry &= ~KFat32CleanShutDownMask; //-- reset ClnShutBit flag
       
   256 
       
   257         if(tmp != fatEntry)
       
   258             {//-- write FAT[1] entry to all available FATs
       
   259                 for(TInt i=0; i<NumberOfFats(); ++i)
       
   260                 {
       
   261                 const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
       
   262                 User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT32[1] entry
       
   263                 }
       
   264             }
       
   265 
       
   266         __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);
       
   267         }
       
   268     else 
       
   269     if(Is16BitFat())
       
   270         {//-- Fat16. 
       
   271             __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16"),DriveNumber(), aClean);
       
   272 
       
   273             if(FatConfig().FAT16_UseCleanShutDownBit())
       
   274                 {
       
   275             TFat16Entry fatEntry;
       
   276             const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
       
   277             TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
       
   278         
       
   279             User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
       
   280 
       
   281             const TFat16Entry tmp = fatEntry;
       
   282         
       
   283             if(aClean)
       
   284                 fatEntry |= KFat16CleanShutDownMask;  //-- set ClnShutBit flag
       
   285             else
       
   286                 fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag
       
   287 
       
   288             if(tmp != fatEntry)
       
   289                 {//-- write FAT[1] entry to all available FATs
       
   290                 for(TInt i=0; i<NumberOfFats(); ++i)
       
   291                     {
       
   292                     const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
       
   293                     User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
       
   294                     }
       
   295                 }
       
   296 		    
       
   297             __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);    
       
   298             }
       
   299             else
       
   300             {
       
   301             __PRINT(_L("#- changing FAT16[1] is disabled in config!"));    
       
   302             }
       
   303         }
       
   304     else
       
   305         {//-- must never get here
       
   306         ASSERT(0);
       
   307         }
       
   308     
       
   309 		//-- Notify the underlying media that the mount is consistent  (ignoring any error for now as there's nothing we can do with it)
       
   310 		(void)LocalDrive()->Finalise(aClean);
       
   311 
       
   312 
       
   313     }
       
   314 
       
   315 //-------------------------------------------------------------------------------------------------------------------
       
   316 
       
   317 /**
       
   318 Determine whether "VolumeClean" (ClnShutBitmask) flag is set.
       
   319 
       
   320 @return ETrue if the volume is marked as clean and EFalse otherwise.
       
   321 @leave  if is called for FAT12 or if read error occured.
       
   322 */
       
   323 TBool CFatMountCB::VolumeCleanL() 
       
   324     {
       
   325 
       
   326     //-- read access to the FAT is through TFatDriveInterface, because CFatTable doesn't allow access to FAT[1]
       
   327     TFatDriveInterface& drive =DriveInterface();
       
   328 
       
   329     if(Is32BitFat())
       
   330         {//-- Fat32
       
   331         TFat32Entry fatEntry;
       
   332         const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
       
   333         TPtr8       ptrFatEntry((TUint8*)&fatEntry, KFatEntrySize);
       
   334         
       
   335         User::LeaveIfError(drive.ReadNonCritical(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT32[1] entry
       
   336         return (fatEntry & KFat32CleanShutDownMask);
       
   337         }
       
   338     else 
       
   339     if(Is16BitFat())
       
   340         {//-- Fat16
       
   341         TFat16Entry fatEntry;
       
   342         const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
       
   343         TPtr8       ptrFatEntry((TUint8*)&fatEntry, KFatEntrySize);
       
   344         
       
   345         User::LeaveIfError(drive.ReadNonCritical(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
       
   346         return (fatEntry & KFat16CleanShutDownMask);
       
   347         }
       
   348     else
       
   349         {//-- Fat12 doesn't support this feature, shan't get here, actually
       
   350         ASSERT(0);
       
   351         User::Leave(KErrNotSupported);
       
   352         return ETrue; //-- to satisfy the compiler
       
   353         }
       
   354     }
       
   355 
       
   356 
       
   357 //-------------------------------------------------------------------------------------------------------------------
       
   358 
       
   359 /**
       
   360 Mount a Fat volume. 
       
   361 
       
   362 @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
       
   363 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
       
   364 */
       
   365 void CFatMountCB::MountL(TBool aForceMount)
       
   366 	{
       
   367 
       
   368     const TInt driveNo = Drive().DriveNumber();
       
   369     
       
   370     __PRINT2(_L("CFatMountCB::MountL() drv:%d, forceMount=%d\n"),driveNo,aForceMount);
       
   371 
       
   372     ASSERT(State() == ENotMounted || State() == EDismounted);
       
   373     SetState(EMounting);
       
   374     SetReadOnly(EFalse);
       
   375    
       
   376 	User::LeaveIfError(CreateDrive(driveNo));
       
   377 
       
   378 
       
   379     //-- read FAT configuration parameters from estart.txt
       
   380     iFatConfig.ReadConfig(driveNo);
       
   381 
       
   382     //-- initialise interface to the low-level drive access
       
   383     if(!iDriverInterface.Init(this))
       
   384         User::LeaveIfError(KErrNoMemory);    
       
   385 
       
   386 	//-- get drive capabilities
       
   387     TLocalDriveCapsV2Buf capsBuf;
       
   388 	User::LeaveIfError(LocalDrive()->Caps(capsBuf));
       
   389 	
       
   390 
       
   391     iSize=capsBuf().iSize;
       
   392     iRamDrive = EFalse;
       
   393 
       
   394     if(capsBuf().iMediaAtt & KMediaAttVariableSize)
       
   395     {//-- this is a RAM drive
       
   396         UserSvr::UnlockRamDrive();
       
   397         iRamDrive = ETrue;
       
   398     }
       
   399 
       
   400 	if(aForceMount)
       
   401 	{//-- the state is "forcedly mounted", special case. This is an inconsistent state.
       
   402         SetState(EInit_Forced);  
       
   403     	return;
       
   404     }
       
   405 
       
   406     //-- read boot sector. If main is damaged, try to use backup one instead if this is not a RAM drive.
       
   407     TFatBootSector bootSector;
       
   408     User::LeaveIfError(ReadBootSector(bootSector, iRamDrive));
       
   409 
       
   410 
       
   411     //-- print out boot sector debug information
       
   412     bootSector.PrintDebugInfo();
       
   413 
       
   414     //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt
       
   415     iFatType = bootSector.FatType();
       
   416     ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector()
       
   417     
       
   418 
       
   419     if(bootSector.RootDirEntries() == 0 && !Is32BitFat())
       
   420     {//-- FAT types mismatch. BPB_RootEntCnt is 0, which can be only for FAT32, but the number of clusters is less 
       
   421      //-- than required for FAT32. Probably this is incorrectly FAT32 formatted media. Put the drive into ReadOnly mode, assuming
       
   422      //-- that is FAT32.
       
   423         __PRINT(_L("FAT type mismatch! Setting drive to ReadOnly mode for FAT32. \n"));
       
   424         iFatType = EFat32; //-- force FAT type to be FAT32
       
   425         SetReadOnly(ETrue);
       
   426     }
       
   427 
       
   428     //-- store volume UID, it can be checked on Remount
       
   429     iUniqueID = bootSector.UniqueID();
       
   430 
       
   431     //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid()
       
   432     iVolParam.Populate(bootSector); 
       
   433 	
       
   434     //-- initialize the volume
       
   435     InitializeL(capsBuf());
       
   436     ASSERT(State()==EInit_R);
       
   437 
       
   438     GetVolumeLabelFromDiskL(bootSector);
       
   439 
       
   440 	__PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State());
       
   441 	}
       
   442 
       
   443 
       
   444 
       
   445 //-------------------------------------------------------------------------------------------------------------------
       
   446 
       
   447 /**
       
   448 Initialize the FAT cache and disk access
       
   449 
       
   450 @param  aLocDrvCaps local drive capabilities
       
   451 @param  aIgnoreFSInfo if ETrue, FSInfo sector shall be ignored. Used on volume remount to force FAT free clusters counting.
       
   452 
       
   453 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
       
   454 */
       
   455 void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool aIgnoreFSInfo/*=EFalse*/) 
       
   456 	{
       
   457     __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber());
       
   458 
       
   459     ASSERT(State() == EMounting); //-- we must get here only from MountL()
       
   460    
       
   461     //========== Find out number of clusters on the volume
       
   462 	if(iRamDrive && SectorsPerCluster()!=1)
       
   463 		{// Align iFirstFreeByte to cluster boundary if internal ram drive
       
   464 		const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2();
       
   465 		const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2();
       
   466 		const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2;
       
   467 		iFirstFreeByte=alignedSector<<SectorSizeLog2();
       
   468 		}
       
   469 	else
       
   470 		{
       
   471 		if(Is32BitFat())
       
   472 			iFirstFreeByte=(NumberOfFats() * FatSizeInBytes()) + (FirstFatSector() << SectorSizeLog2());
       
   473 		else
       
   474 			iFirstFreeByte=RootDirEnd();
       
   475 		}
       
   476 
       
   477 
       
   478 	    {//-- check if volume geometry looks valid
       
   479         const TInt usableSectors=TotalSectors()-(iFirstFreeByte>>SectorSizeLog2());
       
   480 	    iUsableClusters=usableSectors>>(ClusterSizeLog2()-SectorSizeLog2());
       
   481 
       
   482         const TUint32 KMinClusters = 32; //-- absolute minimum number of clusters on the volume
       
   483         const TUint32 KMaxClusters=(TotalSectors()-FirstFatSector()-NumberOfFats()*(FatSizeInBytes()>>SectorSizeLog2())) >> (ClusterSizeLog2()-SectorSizeLog2());
       
   484         
       
   485         if(usableSectors <=0 || iUsableClusters < KMinClusters || iUsableClusters > KMaxClusters)
       
   486             {
       
   487             __PRINT(_L("CFatMountCB::InitializeL() Wrong number of usable cluster/sectors on the volume!"));
       
   488             User::Leave(KErrCorrupt);
       
   489             }
       
   490         }
       
   491 
       
   492 	//========== initialise RawDisk interface
       
   493 	//-- CFatMountCB parameters might have changed, e.g. after formatting. Reconstruct directory cache with new parameters
       
   494 	
       
   495     delete iRawDisk;
       
   496 	iRawDisk=CRawDisk::NewL(*this, aLocDrvCaps);
       
   497     iRawDisk->InitializeL();
       
   498 
       
   499 
       
   500     //========== Try to read FSInfo and deduct number of free clusters and other information from there
       
   501     TBool   bUseDataFromFsInfo = !aIgnoreFSInfo && Is32BitFat(); //-- if ETrue, we are going to use data from FSInfo sector (applicable for FAT32 only)
       
   502     
       
   503     //-- main boot sector shall be valid, otherwise we can't trust data from FSInfo
       
   504     bUseDataFromFsInfo = bUseDataFromFsInfo && iMainBootSecValid;
       
   505 
       
   506     //-- 1. check if using FSInfo is disabled in config
       
   507     if(bUseDataFromFsInfo && !FatConfig().FAT32_UseFSInfoOnMount())
       
   508     {
       
   509         __PRINT(_L("#- FSInfo using is disabled in config!"));
       
   510         bUseDataFromFsInfo = EFalse;
       
   511     }
       
   512 
       
   513 #ifdef  _DEBUG
       
   514     //-- 2. check if FSInfo is disabled by test interface (special debug property). This property is defined and set by the test application.
       
   515     TInt nMntDebugFlags;
       
   516     if(bUseDataFromFsInfo && RProperty::Get(KSID_Test1, DriveNumber(), nMntDebugFlags) == KErrNone)
       
   517         {//-- test property for this drive is defined
       
   518             if(nMntDebugFlags & KMntDisable_FsInfo)
       
   519             {
       
   520             __PRINT(_L("#- FSInfo using is disabled by debug interface."));
       
   521             bUseDataFromFsInfo = EFalse;
       
   522             }
       
   523         }
       
   524 #endif
       
   525 
       
   526     //-- 3. try to read FSInfoSector and its copy if the volume had been properly shut down before (is now clean) 
       
   527     CFatTable::TMountParams fatMntParams;
       
   528     bUseDataFromFsInfo = bUseDataFromFsInfo && VolumeCleanL();
       
   529     if(bUseDataFromFsInfo)
       
   530         {
       
   531         bUseDataFromFsInfo = ProcessFSInfoSectors(fatMntParams);
       
   532         if(!bUseDataFromFsInfo)
       
   533             { 
       
   534             __PRINT1(_L("#- CFatMountCB::ProcessFSInfoSectors() failed. drv:%d"), DriveNumber());
       
   535             }
       
   536         }
       
   537 
       
   538     //========== create and initialise FAT table 
       
   539 	
       
   540     delete iFatTable;
       
   541     iFatTable=CFatTable::NewL(*this, aLocDrvCaps);
       
   542 
       
   543     //-- mount the FAT table. Depending on mount parameters and configuration this method 
       
   544     //-- can do various things, like counting free clusters synchronously if data from FSInfo isn't valid, 
       
   545     //-- or setting up a FAT backround thread and return immediately etc.
       
   546     iFatTable->MountL(fatMntParams);
       
   547    
       
   548     SetState(EInit_R);  //-- the state is "Initialized, but not writen"
       
   549 
       
   550     //-- make a callback, telling FileServer about free space discovered.
       
   551     const TInt64 freeSpace = ((TInt64)FAT().NumberOfFreeClusters()) << ClusterSizeLog2();
       
   552     SetDiskSpaceChange(freeSpace);
       
   553     //========== create and setup leaf direcotry cache if cache limit is set bigger than one 
       
   554 
       
   555 	const TUint32 cacheLimit = iFatConfig.LeafDirCacheSize();
       
   556 	if (cacheLimit > 1)
       
   557 		{
       
   558 		// destroy the old leaf dir cache to avoid memory leak.
       
   559 		delete iLeafDirCache;
       
   560 		iLeafDirCache = CLeafDirCache::NewL(cacheLimit);
       
   561 		}
       
   562 	else
       
   563 		{
       
   564 		iLeafDirCache = NULL;
       
   565 		}
       
   566     
       
   567     __PRINT3(_L("#- CFatMountCB::InitializeL() done. drv:%d, Free clusters:%d, 1st Free cluster:%d"),DriveNumber(), FAT().NumberOfFreeClusters(), FAT().FreeClusterHint());
       
   568 
       
   569     
       
   570 	}
       
   571 
       
   572 //-------------------------------------------------------------------------------------------------------------------
       
   573 
       
   574 /**
       
   575     Write FSInfo sectors to the media
       
   576 
       
   577     @param aMediaPos    Media position to write FSInfo sector to
       
   578     @param aFSInfo      FSInfo structure to write
       
   579     @return System wide error code
       
   580 */
       
   581 TInt CFatMountCB::WriteFSInfoSector(TInt64 aMediaPos, const TFSInfo& aFSInfo)  const
       
   582     {
       
   583     __PRINT2(_L("#- CFatMountCB::WriteFSInfoSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   
       
   584 
       
   585     ASSERT(aMediaPos >= 0 && aMediaPos < FirstFatSector()<<SectorSizeLog2());
       
   586     ASSERT(Is32BitFat());
       
   587 
       
   588     TBuf8<KSizeOfFSInfo> fsInfoSecBuf;
       
   589 
       
   590     //-- put data to the sector buffer
       
   591     aFSInfo.Externalize(fsInfoSecBuf);
       
   592 
       
   593 	TInt r=LocalDrive()->Write(aMediaPos, fsInfoSecBuf);
       
   594 	if (r!=KErrNone)
       
   595         {
       
   596         __PRINT2(_L("CFatMountCB::WriteFSInfoSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
       
   597         }
       
   598 
       
   599     return r;
       
   600     }
       
   601 
       
   602 //-------------------------------------------------------------------------------------------------------------------
       
   603 /**
       
   604     Read the FSInfo structure from media 
       
   605 
       
   606     @param aMediaPos    Media position to read FSInfo sector from
       
   607     @param aFSInfo      data read from FSInfo structure
       
   608     @return System wide error code
       
   609 */
       
   610 TInt CFatMountCB::ReadFSInfoSector(TInt64 aMediaPos, TFSInfo& aFSInfo)  const
       
   611     {
       
   612     __PRINT2(_L("#- CFatMountCB::ReadFSInfoSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   
       
   613 
       
   614     ASSERT(aMediaPos >= 0 && aMediaPos < FirstFatSector()<<SectorSizeLog2());
       
   615     ASSERT(Is32BitFat());
       
   616 
       
   617     TBuf8<KSizeOfFSInfo> fsInfoSecBuf;
       
   618 
       
   619     TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFSInfo, fsInfoSecBuf); 
       
   620 	if (r!=KErrNone)
       
   621 	{
       
   622 		__PRINT2(_L("CFatMountCB::ReadFSInfoSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
       
   623 	    return r;
       
   624 	}
       
   625 
       
   626     //-- take FSInfo data from the buffer
       
   627     aFSInfo.Internalize(fsInfoSecBuf);
       
   628     
       
   629     return KErrNone;
       
   630     }
       
   631 
       
   632 /**
       
   633 Checks for end of file for all Fat types
       
   634 
       
   635 @param aCluster Cluster to check
       
   636 @return Result of test
       
   637 */
       
   638 TBool CFatMountCB::IsEndOfClusterCh(TInt aCluster) const
       
   639 	{
       
   640 	if(Is32BitFat())
       
   641 		return(aCluster>=(TInt)0x0FFFFFF8 && aCluster<=(TInt)0x0FFFFFFF);
       
   642 	else if(Is16BitFat())
       
   643 		return(aCluster>=0xFFF8 && aCluster<=0xFFFF);
       
   644 	else
       
   645 		return(aCluster>=0xFF8 && aCluster<=0xFFF);
       
   646 	}
       
   647 
       
   648 /**
       
   649 Set a cluster to the end of cluster chain marker
       
   650 
       
   651 @param aCluster cluster to set to end of chain marker
       
   652 */
       
   653 void CFatMountCB::SetEndOfClusterCh(TInt &aCluster) const
       
   654 	{
       
   655 	if(Is32BitFat())
       
   656 		aCluster=EOF_32Bit;
       
   657 	else if(Is16BitFat())
       
   658 		aCluster=EOF_16Bit;
       
   659 	else
       
   660 		aCluster=EOF_12Bit;
       
   661 	}
       
   662 
       
   663 /**
       
   664 Initialize data to represent the root directory
       
   665 
       
   666 @param anEntry Entry to initialise
       
   667 */
       
   668 void CFatMountCB::InitializeRootEntry(TFatDirEntry & anEntry) const
       
   669 	{
       
   670 	anEntry.SetName(_L8("ROOT"));
       
   671 	anEntry.SetAttributes(KEntryAttDir);
       
   672 	anEntry.SetStartCluster(RootClusterNum()); //--iRootClusterNum is 0 for FAT12/16
       
   673 	}
       
   674 
       
   675 
       
   676 
       
   677 /**
       
   678 Implementation of CMountCB::FileSystemSubType(). Retrieves the sub type of Fat file system
       
   679 and returns the name as a descriptor.
       
   680 
       
   681 @param aName Name of the sub type of Fat file system
       
   682 @return KErrNone if successful; KErrArgument if aName is not long enough; KErrNotReady if
       
   683 		the mount is not ready.
       
   684 
       
   685 @see CMountCB::FileSystemSubType()
       
   686 */
       
   687 TInt CFatMountCB::SubType(TDes& aName) const
       
   688 	{
       
   689 	if(aName.MaxLength() < 5)
       
   690 		return KErrArgument;
       
   691 	
       
   692 	switch (iFatType)
       
   693 		{
       
   694 		case EFat12:
       
   695 			{
       
   696 			aName = KFSSubType_FAT12;
       
   697 			return KErrNone;
       
   698 			}
       
   699 		case EFat16:
       
   700 			{
       
   701 			aName = KFSSubType_FAT16;
       
   702 			return KErrNone;
       
   703 			}
       
   704 		case EFat32:
       
   705 			{
       
   706 			aName = KFSSubType_FAT32;
       
   707 			return KErrNone;
       
   708 			}
       
   709 		default:
       
   710 		// case EInvalidFatType
       
   711 			return KErrNotReady;
       
   712 		}
       
   713 	}
       
   714 
       
   715 
       
   716 //-------------------------------------------------------------------------------------------------------------------
       
   717 
       
   718 /**
       
   719     Try to extract useful information from the FSInfo sectors.
       
   720     The information from FSInfo sectors will be trusted only if there are main and backup sectors,
       
   721     they are both valid and the same.
       
   722 
       
   723     @param  aFatInitParams  on success will contain the number of free clusters on the volume and 1st free cluster number from the FSInfo 
       
   724     @return ETrue on success.
       
   725 */
       
   726 TBool CFatMountCB::ProcessFSInfoSectors(CFatTable::TMountParams& aFatInitParams) const
       
   727     {
       
   728 
       
   729     aFatInitParams.iFreeClusters = 0;
       
   730     aFatInitParams.iFirstFreeCluster = 0;
       
   731     aFatInitParams.iFsInfoValid = EFalse;
       
   732 
       
   733     const TUint32 currFsInfoSec   = iVolParam.FSInfoSectorNum();    //-- values from the boot sector
       
   734     const TUint32 currFsInfoBkSec = iVolParam.BkFSInfoSectorNum();                                                                              
       
   735 
       
   736     if(!Is32BitFat() || currFsInfoSec < KFSInfoSectorNum || currFsInfoSec >= FirstFatSector())
       
   737         {
       
   738         ASSERT(0);  //-- main FSInfo sector must have sensible location
       
   739         return EFalse;
       
   740         }
       
   741 
       
   742     if(currFsInfoBkSec < KFSInfoSectorNum || currFsInfoBkSec >= FirstFatSector() || currFsInfoBkSec <= currFsInfoSec)
       
   743         return EFalse; //-- something is wrong with backup copy location
       
   744 
       
   745     TFSInfo fsInfo;
       
   746 	TInt    nRes;
       
   747 
       
   748     //-- 1. read and validate main FS Info sector
       
   749     nRes = ReadFSInfoSector(currFsInfoSec << SectorSizeLog2(), fsInfo);
       
   750     if(nRes != KErrNone)
       
   751         return EFalse;
       
   752 
       
   753     fsInfo.PrintDebugInfo();
       
   754 
       
   755     if(!fsInfo.IsValid())
       
   756         return EFalse;
       
   757 
       
   758     const TUint32 freeCount=fsInfo.FreeClusterCount(); // last known free cluster count
       
   759 	const TUint32 nextFree =fsInfo.NextFreeCluster();  // hint to file system as to where to start looking for free clusters
       
   760 
       
   761     //-- 2. read and check backup FS Info sector, it must be the same as the main one
       
   762     nRes = ReadFSInfoSector(currFsInfoBkSec << SectorSizeLog2(), fsInfo);
       
   763     
       
   764     if(nRes != KErrNone || !fsInfo.IsValid() || freeCount != fsInfo.FreeClusterCount() || nextFree != fsInfo.NextFreeCluster())
       
   765     {
       
   766         __PRINT(_L("#- CFatMountCB::ProcessFSInfoSectors(): copies of FSInfo are different!"));
       
   767         return EFalse;
       
   768     }
       
   769 
       
   770     if(freeCount < 1 || freeCount > UsableClusters())
       
   771         return EFalse; //-- looks like invalid value
       
   772     
       
   773     if(nextFree < KFatFirstSearchCluster || nextFree >= UsableClusters()+KFatFirstSearchCluster)
       
   774         return EFalse; //-- looks like invalid value
       
   775 
       
   776     //-- success
       
   777     aFatInitParams.iFreeClusters = freeCount;
       
   778     aFatInitParams.iFirstFreeCluster = nextFree;
       
   779     aFatInitParams.iFsInfoValid = ETrue;
       
   780     
       
   781     return ETrue;
       
   782     }
       
   783 
       
   784 //-------------------------------------------------------------------------------------------------------------------
       
   785 /**
       
   786     Internal helper method. Writes FSInfo sector and its backup copy to the volume if necessary. 
       
   787     
       
   788     @param  aInvalidateFSInfo if ETrue, FSInfo data (free clusters count) will be invalidated.
       
   789                               otherwise, data from the CFatTable object will be used
       
   790                                     
       
   791     @leave  if disk opertion fails
       
   792 */
       
   793 void CFatMountCB::DoUpdateFSInfoSectorsL(TBool aInvalidateFSInfo)
       
   794     {
       
   795     __PRINT2(_L("#- CFatMountCB::DoUpdateFSInfoSectorsL(%d) drv:%d"),aInvalidateFSInfo, Drive().DriveNumber());
       
   796     
       
   797     ASSERT(Is32BitFat());
       
   798     
       
   799     if(!aInvalidateFSInfo)
       
   800         {
       
   801         ASSERT(FAT().ConsistentState());
       
   802         }
       
   803         
       
   804     //-- 1. check that FSInfoSector numbers are valid
       
   805     TBool bCanWriteFSInfo_Main = EFalse;//-- if ETrue, it's OK to write main FSInfo sector
       
   806     TBool bCanWriteFSInfo_Bk = EFalse;  //-- if ETrue, it's OK to write backup FSInfo sector
       
   807 
       
   808     const TUint32 currFsInfoSec   = iVolParam.FSInfoSectorNum();    //-- values from the boot sector
       
   809     const TUint32 currFsInfoBkSec = iVolParam.BkFSInfoSectorNum();
       
   810         
       
   811     if(currFsInfoSec > 0 && currFsInfoSec < FirstFatSector())
       
   812         {//-- seems to be OK
       
   813         bCanWriteFSInfo_Main = ETrue;
       
   814         }
       
   815     else
       
   816         {
       
   817         __PRINT1(_L("#- DoUpdateFSInfoSectorsL() iFSInfoSectorNum is wrong!: sec:%d"), currFsInfoSec);
       
   818         }
       
   819 
       
   820     if(currFsInfoBkSec > 0 && currFsInfoBkSec < FirstFatSector() && currFsInfoBkSec > currFsInfoSec)
       
   821         {//-- seems to be OK
       
   822         bCanWriteFSInfo_Bk = bCanWriteFSInfo_Main;
       
   823         }
       
   824     else
       
   825         {
       
   826         __PRINT1(_L("#- DoUpdateFSInfoSectorsL() iBkFSInfoSectorNum is wrong!: sec:%d"),currFsInfoBkSec);
       
   827         }
       
   828 
       
   829     if(!bCanWriteFSInfo_Main && !bCanWriteFSInfo_Bk)
       
   830         return; //-- nothing to do
       
   831 
       
   832     
       
   833     const TUint32 KFsInfoSecPos_Main = currFsInfoSec   << SectorSizeLog2();  //-- main FSInfo sector media position
       
   834     const TUint32 KFsInfoSecPos_Bk   = currFsInfoBkSec << SectorSizeLog2();  //-- backup FSInfo sector media position
       
   835     
       
   836     TFSInfo fsInfoSector;
       
   837 
       
   838     TBool bNeedWriteFSInfo_Main = EFalse;
       
   839     TBool bNeedWriteFSInfo_Bk = EFalse;
       
   840 
       
   841     
       
   842     const TUint32 KInvalidVal = 0xFFFFFFFF; //-- invalid value for FSInfo fields, see FAT specs
       
   843     
       
   844     //-- we need here _exact_ number of free clusters, so make FAT().NumberOfFreeClusters() operation synchronous
       
   845     const TUint32 KFreeClusters    = aInvalidateFSInfo ? KInvalidVal : FAT().NumberOfFreeClusters(ETrue); 
       
   846     const TUint32 KNextFreeCluster = aInvalidateFSInfo ? KInvalidVal : FAT().FreeClusterHint(); 
       
   847     
       
   848     //-- check if the main FSInfo sector differs from the FAT information
       
   849     if(bCanWriteFSInfo_Main)
       
   850         {
       
   851         User::LeaveIfError(ReadFSInfoSector(KFsInfoSecPos_Main, fsInfoSector));
       
   852         bNeedWriteFSInfo_Main = !fsInfoSector.IsValid() ||
       
   853                                 fsInfoSector.FreeClusterCount() != KFreeClusters || 
       
   854                                 fsInfoSector.NextFreeCluster()  != KNextFreeCluster; 
       
   855         }
       
   856 
       
   857     //-- check if the backup FSInfo sector differs from the FAT information
       
   858     if(bCanWriteFSInfo_Bk)
       
   859         {
       
   860         User::LeaveIfError(ReadFSInfoSector(KFsInfoSecPos_Bk, fsInfoSector));
       
   861         bNeedWriteFSInfo_Bk =   !fsInfoSector.IsValid() ||
       
   862                                 fsInfoSector.FreeClusterCount() != KFreeClusters ||
       
   863                                 fsInfoSector.NextFreeCluster()  != KNextFreeCluster; 
       
   864         }
       
   865 
       
   866     //-- setup data in FSInfo sector to write
       
   867     fsInfoSector.Initialise();
       
   868     fsInfoSector.SetFreeClusterCount(KFreeClusters);
       
   869     fsInfoSector.SetNextFreeCluster(KNextFreeCluster);
       
   870 
       
   871     if(!bNeedWriteFSInfo_Main && !bNeedWriteFSInfo_Bk)
       
   872         return; //-- nothing to do
       
   873 
       
   874     SetVolumeCleanL(EFalse); //-- mark volume dirty, just in case something will happen on FSInfo sectors write
       
   875 
       
   876     if(bNeedWriteFSInfo_Main)
       
   877         User::LeaveIfError(WriteFSInfoSector(KFsInfoSecPos_Main, fsInfoSector));
       
   878 
       
   879     if(bNeedWriteFSInfo_Bk)
       
   880         User::LeaveIfError(WriteFSInfoSector(KFsInfoSecPos_Bk, fsInfoSector));
       
   881 
       
   882     }
       
   883 
       
   884 //-------------------------------------------------------------------------------------------------------------------
       
   885 
       
   886 /**
       
   887     CFatMountCB control method.
       
   888     @param  aLevel  specifies the operation to perfrom on the mount
       
   889     @param  aOption specific option for the given operation
       
   890     @param  aParam  pointer to generic parameter, its meaning depends on aLevel and aOption
       
   891 
       
   892     @return standard error code.
       
   893 */
       
   894 TInt CFatMountCB::MountControl(TInt aLevel, TInt aOption, TAny* aParam)
       
   895     {
       
   896     __PRINT3(_L("CFatMountCB::MountControl() drv:%d, level:%d, opt:%d"),Drive().DriveNumber(), aLevel, aOption);
       
   897     
       
   898     TInt nRes = KErrNotSupported; 
       
   899     
       
   900     if(aLevel == ECheckFsMountable)
       
   901         {
       
   902         return MntCtl_DoCheckFileSystemMountable();
       
   903         }
       
   904     
       
   905     //-- todo: move these functions code into separate methods ??
       
   906 
       
   907     //-- mount state query: check if is in finalised state 
       
   908     if(aLevel == EMountStateQuery && aOption == ESQ_IsMountFinalised)
       
   909         {
       
   910         TBool bFinalised;
       
   911         nRes = IsFinalised(bFinalised);
       
   912         if(nRes == KErrNone)
       
   913             {
       
   914             *((TBool*)aParam) = bFinalised;
       
   915             }
       
   916         
       
   917         return nRes;
       
   918         }
       
   919 
       
   920     //-- mount-specific volume parameters queries that might not be handled by CFatMountCB::VolumeL
       
   921     if(aLevel == EMountVolParamQuery)
       
   922         {
       
   923         ASSERT(ConsistentState()); //-- volume state shall be consistent, otherwise its parameters do not make sense
       
   924         switch(aOption)
       
   925             {
       
   926             //-- Request a certain amount of free space on the volume.
       
   927             case ESQ_RequestFreeSpace:
       
   928                 {
       
   929                 TUint64* pVal = (TUint64*)aParam; //-- in: number of free bytes on the volume required, out: resulted amount of free space.
       
   930                 const TUint32 KClustersRequired = (TUint32)((*pVal + ClusterSize() - 1) >> ClusterSizeLog2());
       
   931                 __PRINT2(_L("MountControl() ReqFreeSpace:%LU, clusters:%d"), *pVal, KClustersRequired);    
       
   932 
       
   933                 if(KClustersRequired)
       
   934                     {//-- actually, this doesn't guarantee that it will finally be KClustersRequired available.
       
   935                     (void)FAT().RequestFreeClusters(KClustersRequired);  
       
   936                     }
       
   937          
       
   938                 const TUint32 freeClusters = FAT().NumberOfFreeClusters(EFalse); //-- _current_ amount of free clusters  
       
   939                 *pVal = (TInt64)freeClusters << ClusterSizeLog2();
       
   940 
       
   941                 return KErrNone;
       
   942                 }
       
   943 
       
   944             //-- A request to obtain the _current_ amount of free space on the volume asynchronously, without blocking.
       
   945             case ESQ_GetCurrentFreeSpace:
       
   946                 {
       
   947                 TUint64* pVal = (TUint64*)aParam; //-- out: resulted amount of free space.
       
   948 
       
   949                 const TUint32 freeClusters = FAT().NumberOfFreeClusters(EFalse); //-- _current_ amount of free clusters  
       
   950                 *pVal = (TInt64)freeClusters << ClusterSizeLog2();
       
   951                 __PRINT1(_L("MountControl() Asynch. request; curent amount of free clusters: %d"), freeClusters);
       
   952 
       
   953                 return KErrNone;
       
   954                 }
       
   955         
       
   956             //-- A request to obtain size of the mounted volume without blocking (CMountCB::VolumeL() can block).
       
   957             case ESQ_MountedVolumeSize:
       
   958                 {
       
   959                 if(iRamDrive)
       
   960                     return KErrNotSupported; //-- it requires knowledge of free space on the volume
       
   961     
       
   962                 TUint64* pVal = (TUint64*)aParam; 
       
   963                 *pVal = iSize; //-- physical drive size
       
   964 
       
   965                 //-- take into account space occupied by FAT table, etc.
       
   966                 *pVal -= ClusterBasePosition(); 
       
   967                 *pVal=(*pVal >> ClusterSizeLog2()) << ClusterSizeLog2();  //-- round down to cluster size
       
   968 
       
   969                 __PRINT1(_L("MountControl() MountedVolumeSize:%LU"), *pVal);
       
   970                 return KErrNone;
       
   971                 }
       
   972 
       
   973             default:
       
   974             __PRINT1(_L("MountControl() unsupported opt:%d"), aOption);
       
   975             ASSERT(0);
       
   976             break;
       
   977             };
       
   978 
       
   979         }
       
   980 
       
   981         //-- File System - specific queries 
       
   982         if(aLevel == EMountFsParamQuery && aOption == ESQ_GetMaxSupportedFileSize)
       
   983             {//-- this is a query to provide the max. supported file size; aParam is a pointer to TUint64 to return the value
       
   984             *(TUint64*)aParam = KMaxSupportedFatFileSize;    
       
   985             return KErrNone;
       
   986             }
       
   987 
       
   988 
       
   989     
       
   990     
       
   991     return KErrNotSupported; 
       
   992     }
       
   993 
       
   994 //-----------------------------------------------------------------------------------------
       
   995 
       
   996 /**
       
   997 Reports whether the specified interface is supported - if it is,
       
   998 the supplied interface object is modified to it
       
   999 
       
  1000 @param aInterfaceId     The interface of interest
       
  1001 @param aInterface       The interface object
       
  1002 @return                 KErrNone if the interface is supported, otherwise KErrNotFound 
       
  1003 
       
  1004 @see CMountCB::GetInterface()
       
  1005 */
       
  1006 TInt CFatMountCB::GetInterface(TInt aInterfaceId, TAny*& aInterface,TAny* aInput)
       
  1007     {
       
  1008     switch(aInterfaceId)
       
  1009         {
       
  1010         case (CMountCB::EFileAccessor):
       
  1011             ((CMountCB::MFileAccessor*&) aInterface) = this;
       
  1012             return KErrNone;
       
  1013         
       
  1014         case (CMountCB::EGetFileSystemSubType):
       
  1015             aInterface = (MFileSystemSubType*) (this);
       
  1016             return KErrNone;
       
  1017 
       
  1018         case (CMountCB::EGetClusterSize):
       
  1019             aInterface = (MFileSystemClusterSize*) (this);
       
  1020             return KErrNone;
       
  1021 
       
  1022         case CMountCB::ELocalBufferSupport:
       
  1023             // RAM drives doesn't support local buffers (this results in file caching being disabled)
       
  1024             if (iRamDrive) 
       
  1025                 return KErrNotSupported;
       
  1026             else
       
  1027                 return LocalDrive()->LocalBufferSupport();
       
  1028         
       
  1029 		case EGetProxyDrive:
       
  1030 			((CProxyDrive*&)aInterface) = LocalDrive();
       
  1031 			return KErrNone;
       
  1032         
       
  1033         case CMountCB::EFileExtendedInterface:
       
  1034        		// For supporting large file ReadFileSection
       
  1035        		((CMountCB::MFileExtendedInterface*&) aInterface) = this;
       
  1036            	return KErrNone;
       
  1037         
       
  1038         default:
       
  1039             return(CMountCB::GetInterface(aInterfaceId, aInterface, aInput));
       
  1040         }
       
  1041     }
       
  1042 
       
  1043 //-----------------------------------------------------------------------------------------
       
  1044 void CFatMountCB::ReadSection64L(const TDesC& aName, TInt64 aPos, TAny* aTrg, TInt aLength, const RMessagePtr2& aMessage)
       
  1045 // From CMountCB::MFileExtendedInterface
       
  1046 	{
       
  1047     __PRINT(_L("CFatMountCB::ReadSection64L"));
       
  1048 	
       
  1049     CheckStateConsistentL();
       
  1050     TEntryPos dosEntryPos(RootIndicator(),0);
       
  1051     TFatDirEntry dosEntry;
       
  1052     TFileName fileName; 
       
  1053 
       
  1054     TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // There is always a path delimiter
       
  1055     TLeafDirData leafDir(0);
       
  1056     dosEntryPos.iCluster=FindLeafDirL(aName.Left(namePos), leafDir);
       
  1057     dosEntryPos.iPos=0;
       
  1058     TEntryPos firstEntryPos;
       
  1059     TFatDirEntry firstEntry;
       
  1060     DoFindL(aName.Mid(namePos),KEntryAttMaskSupported,
       
  1061     		firstEntryPos,firstEntry,dosEntryPos,dosEntry,
       
  1062     		fileName,KErrNotFound,
       
  1063     		NULL,
       
  1064     		leafDir);
       
  1065     
       
  1066 //  Check that reading from aPos for aLength lies within the file
       
  1067 //  if aPos is within the file, and aLength is too long, read up to EOF
       
  1068 //  If aPos is beyond the end of the file, return a zero length descriptor
       
  1069 
       
  1070 	TInt64 fileSize = MAKE_TINT64(0,dosEntry.Size());
       
  1071 	if (aPos>=fileSize)
       
  1072         User::Leave(KErrEof);
       
  1073 	
       
  1074     if (aPos+aLength>fileSize)
       
  1075         aLength=(TInt)(fileSize-aPos);
       
  1076     
       
  1077     TInt cluster=StartCluster(dosEntry);	
       
  1078 	TInt64 pos = aPos;
       
  1079 	
       
  1080     TInt endCluster;
       
  1081     TInt clusterSize=1<<ClusterSizeLog2();      //  Size of file clusters
       
  1082 	TInt readTotal = 0;
       
  1083 	
       
  1084 	// Total number of clusters in file
       
  1085     TInt maxClusters=(TInt)((fileSize+clusterSize-1)>>ClusterSizeLog2());
       
  1086 
       
  1087 	// Read data
       
  1088     FOREVER
       
  1089         {
       
  1090 		//  Get the maximum number of clusters that can be read contiguously
       
  1091         TInt64 clusterListLen=FAT().CountContiguousClustersL(cluster,endCluster,maxClusters);
       
  1092         __ASSERT_DEBUG(clusterListLen>0,Fault(EReadFileSectionFailed));
       
  1093 
       
  1094 		//  If start position within this block, then read some data
       
  1095         if (pos<(clusterListLen<<ClusterSizeLog2()))
       
  1096             {
       
  1097 			//  Read the remaining length or the entire cluster block whichever is smaller
       
  1098 			TInt readLength = (TInt)Min((TInt64)(aLength-readTotal),(clusterListLen<<ClusterSizeLog2())-pos);
       
  1099 			__ASSERT_DEBUG(readLength>0,Fault(EReadFileSectionFailed));
       
  1100 			TInt64 dataAddress=(FAT().DataPositionInBytes(cluster))+pos;
       
  1101 			iRawDisk->ReadL(dataAddress,readLength,aTrg,aMessage,readTotal);
       
  1102 			readTotal += readLength;
       
  1103 
       
  1104 			if (readTotal == aLength)
       
  1105 				return;
       
  1106 
       
  1107 			pos += readLength;
       
  1108 			}
       
  1109 		
       
  1110 		// Get the next cluster in file
       
  1111 		pos-=(clusterListLen<<ClusterSizeLog2());
       
  1112 #if defined(_DEBUG)
       
  1113 		TBool remainingClusters=
       
  1114 #endif
       
  1115 			((CFatMountCB*)this)->FAT().GetNextClusterL(endCluster);
       
  1116 		__ASSERT_DEBUG(remainingClusters,Fault(EReadFileSectionFailed));		
       
  1117 		cluster=endCluster;
       
  1118 		}
       
  1119     }