userlibandfileserver/fileserver/sfat/sl_mnt16.cpp
changeset 0 a41df078684a
child 15 4122176ea935
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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_mnt16.cpp
       
    15 // CFatMountCB code, specific to the EFAT.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     Write aligned members of TFatBootSector to media
       
    31  
       
    32     @param  aMediaPos   media position the data will be written to
       
    33     @param  aBootSector data to write
       
    34     @return Media write error code
       
    35 */
       
    36 TInt CFatMountCB::DoWriteBootSector(TInt64 aMediaPos, const TFatBootSector& aBootSector) const
       
    37     {
       
    38     __PRINT2(_L("#- CFatMountCB::DoWriteBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   
       
    39 
       
    40     ASSERT(aMediaPos>=0);
       
    41 
       
    42     TBuf8<KDefaultSectorSize> bootSecBuf(KDefaultSectorSize);
       
    43     bootSecBuf.FillZ();
       
    44 
       
    45     //-- externalize boot sector to the data buffer
       
    46     aBootSector.Externalize(bootSecBuf);
       
    47 
       
    48     //-- put a boot sector signature to the last 2 bytes
       
    49     bootSecBuf[KDefaultSectorSize-2] = 0x55;
       
    50     bootSecBuf[KDefaultSectorSize-1] = 0xaa;
       
    51 
       
    52     //-- write boot sector to the media
       
    53     TInt r=LocalDrive()->Write(aMediaPos, bootSecBuf);
       
    54     if (r!=KErrNone)
       
    55         {//-- write failure
       
    56         __PRINT2(_L("CFatMountCB::DoWriteBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
       
    57         }
       
    58 
       
    59     return r;
       
    60     }
       
    61 
       
    62 //-------------------------------------------------------------------------------------------------------------------
       
    63 
       
    64 /**
       
    65     Read non aligned boot data from media into TFatBootSector structure
       
    66 
       
    67     @param  aMediaPos   media position the data will be read from
       
    68     @param  aBootSector refrence to TFatBootSector populate
       
    69     @return Media read error code
       
    70 */
       
    71 TInt CFatMountCB::DoReadBootSector(TInt64 aMediaPos, TFatBootSector& aBootSector) const 
       
    72     {
       
    73     __PRINT2(_L("#- CFatMountCB::DoReadBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   
       
    74 
       
    75     ASSERT(aMediaPos>=0);
       
    76 
       
    77     TBuf8<KSizeOfFatBootSector> bootSecBuf(KSizeOfFatBootSector);
       
    78     
       
    79     //-- read boot sector from the media
       
    80     TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf);
       
    81     if (r != KErrNone)
       
    82         {
       
    83         __PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
       
    84 
       
    85 	    //-- fiddling with the error code; taken from MountL()
       
    86         if (r==KErrNotSupported)
       
    87 		    return KErrNotReady;
       
    88     #if defined(_LOCKABLE_MEDIA)
       
    89 	    else if(r==KErrLocked)
       
    90 		    return KErrLocked;
       
    91     #endif
       
    92 	    else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
       
    93                 return KErrCorrupt; 
       
    94 
       
    95         return r;
       
    96         }
       
    97 
       
    98     ASSERT(r==KErrNone);
       
    99 
       
   100     //-- initialise TFatBootSector object
       
   101     aBootSector.Internalize(bootSecBuf);
       
   102 
       
   103     //-- Validate the partition size, and fix up if the out of bounds
       
   104     TLocalDriveCapsV2Buf localDriveCaps;
       
   105     r = LocalDrive()->Caps(localDriveCaps);
       
   106     ASSERT(r==KErrNone);
       
   107     
       
   108     if(!(localDriveCaps().iMediaAtt & KMediaAttVariableSize))
       
   109         {//-- this is not a RAM drive.
       
   110         const TUint32 maxSectors = I64LOW(localDriveCaps().iSize >> KDefSectorSzLog2);
       
   111 
       
   112         if(aBootSector.TotalSectors())
       
   113             aBootSector.SetTotalSectors(Min(aBootSector.TotalSectors(), maxSectors));
       
   114         else
       
   115             aBootSector.SetHugeSectors(Min(aBootSector.HugeSectors(), maxSectors));
       
   116         }
       
   117 
       
   118     return KErrNone;
       
   119     }
       
   120 
       
   121 //-------------------------------------------------------------------------------------------------------------------
       
   122 
       
   123 /**
       
   124     Read and validate the boot sector.
       
   125     @param      aBootSector reference to the boot sector object to be read.
       
   126     @param      aDoNotReadBkBootSec if true, there won't be an attempt to read backup sector (N/A for FAT12/16)
       
   127     @return     standard error code.
       
   128 */
       
   129 TInt CFatMountCB::ReadBootSector(TFatBootSector& aBootSector, TBool /*aDoNotReadBkBootSec=EFalse*/)
       
   130     {
       
   131     //-- read main boot sector from the sector 0
       
   132     TInt nRes = DoReadBootSector(KBootSectorNum << KDefSectorSzLog2, aBootSector); 
       
   133     if(nRes == KErrNone)
       
   134         {
       
   135         if(aBootSector.IsValid())
       
   136             {//-- main boot sector is valid, everything is OK
       
   137             return KErrNone;
       
   138             }
       
   139         else
       
   140             {
       
   141             __PRINT(_L("Boot Sector is invalid! dump:\n"));
       
   142             aBootSector.PrintDebugInfo();
       
   143             return KErrCorrupt;
       
   144             }
       
   145         }
       
   146 
       
   147     //-- can't read boot sector
       
   148     return nRes;
       
   149     }
       
   150 
       
   151 //-------------------------------------------------------------------------------------------------------------------
       
   152 
       
   153 /**
       
   154 Write a new volume label to BPB in media
       
   155 
       
   156 @param aVolumeLabel Descriptor containing the new volume label
       
   157 @leave 
       
   158 */
       
   159 void CFatMountCB::WriteVolumeLabelL(const TDesC8& aVolumeLabel) const
       
   160 	{
       
   161     if(aVolumeLabel.Length() > KVolumeLabelSize)
       
   162         User::Leave(KErrArgument);
       
   163 
       
   164 	User::LeaveIfError(LocalDrive()->Write(KFat16VolumeLabelPos,aVolumeLabel)); 
       
   165     }
       
   166 
       
   167 
       
   168 
       
   169 //-------------------------------------------------------------------------------------------------------------------
       
   170 
       
   171 const TUint16 KFat16CleanShutDownMask	= 0x08000;    ///< Mask used to indicate test clean/dirty bit for Fat16
       
   172 
       
   173 /**
       
   174 Set or reset "VolumeClean" (ClnShutBitmask) flag.
       
   175 
       
   176 @param  aClean if ETrue, marks the volume as clean, otherwise as dirty.
       
   177 @leave  if write error occured.        
       
   178 */
       
   179 void CFatMountCB::SetVolumeCleanL(TBool aClean) 
       
   180     {
       
   181 	//-- The volume can't be set clean if there are objects opened on it. This precondition must be checked before calling this function
       
   182     if(aClean && LockStatus()!=0)
       
   183         {
       
   184         __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
       
   185         ASSERT(0);
       
   186         User::Leave(KErrInUse);
       
   187         return;
       
   188         }
       
   189 
       
   190     if(FatType() == EFat12)
       
   191         {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive
       
   192 		 //   (ignoring any error for now as there's nothing we can do with it)
       
   193 		(void)LocalDrive()->Finalise(aClean);
       
   194 		return;
       
   195         }
       
   196 
       
   197     //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. 
       
   198     //-- this is because CFatTable doesn't allow access to FAT[1]
       
   199 
       
   200     if(Is16BitFat())
       
   201         {//-- Fat16
       
   202         __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16, efat.fsy"),DriveNumber(), aClean);
       
   203 
       
   204         if(FatConfig().FAT16_UseCleanShutDownBit())
       
   205             {
       
   206 
       
   207             TFat16Entry fatEntry;
       
   208             const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
       
   209             TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
       
   210         
       
   211             User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
       
   212         
       
   213             const TFat16Entry tmp = fatEntry;
       
   214         
       
   215             if(aClean)
       
   216                 fatEntry |= KFat16CleanShutDownMask;  //-- set ClnShutBit flag
       
   217             else
       
   218                 fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag
       
   219 
       
   220             if(tmp != fatEntry)
       
   221                 {//-- write FAT[1] entry to all available FATs
       
   222                 for(TInt i=0; i<NumberOfFats(); ++i)
       
   223                     {
       
   224                     const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
       
   225                     User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
       
   226                     }
       
   227                 }
       
   228 		    
       
   229 		     //-- Notify the underlying media that the mount is consistent
       
   230 		     //   (ignoring any error for now as there's nothing we can do with it)
       
   231 		    (void)LocalDrive()->Finalise(aClean);
       
   232 
       
   233             __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);    
       
   234         
       
   235             }
       
   236         else //if(FatConfig().FAT16_UseCleanShutDownBit())
       
   237             {
       
   238             __PRINT(_L("#- changing FAT16[1] is disabled in config!"));    
       
   239             }
       
   240        
       
   241         }// if(Is16BitFat())
       
   242     else
       
   243         {//-- must never get here
       
   244         ASSERT(0);
       
   245         }
       
   246     
       
   247     }
       
   248 
       
   249 //-------------------------------------------------------------------------------------------------------------------
       
   250 
       
   251 /**
       
   252 Determine whether "VolumeClean" (ClnShutBitmask) flag is set.
       
   253 
       
   254 @return ETrue if the volume is marked as clean and EFalse otherwise.
       
   255 @leave  if is called for FAT12 or if read error occured.
       
   256 */
       
   257 TBool CFatMountCB::VolumeCleanL()
       
   258     {
       
   259     TFatDriveInterface& drive = DriveInterface();
       
   260     
       
   261     if(Is16BitFat())
       
   262         {//-- Fat16
       
   263         TFat16Entry fatEntry;
       
   264         const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
       
   265         TPtr8       ptrFatEntry((TUint8*)&fatEntry, KFatEntrySize);
       
   266         
       
   267         User::LeaveIfError(drive.ReadNonCritical(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
       
   268         return (fatEntry & KFat16CleanShutDownMask);
       
   269         }
       
   270     else
       
   271         {//-- Fat12 doesn't support this feature, shan't get here, actually
       
   272         ASSERT(0);
       
   273         User::Leave(KErrNotSupported);
       
   274         return ETrue; //-- to satisfy the compiler
       
   275         }
       
   276     }
       
   277 
       
   278 //-------------------------------------------------------------------------------------------------------------------
       
   279 
       
   280 /**
       
   281 Mount a Fat volume. 
       
   282 
       
   283 @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
       
   284 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
       
   285 */
       
   286 void CFatMountCB::MountL(TBool aForceMount)
       
   287 	{
       
   288     const TInt driveNo = Drive().DriveNumber();
       
   289     
       
   290     __PRINT2(_L("CFatMountCB::MountL() drv:%d, forceMount=%d\n"),driveNo,aForceMount);
       
   291 
       
   292     ASSERT(State() == ENotMounted || State() == EDismounted);
       
   293     SetState(EMounting);
       
   294     SetReadOnly(EFalse);
       
   295    
       
   296 
       
   297 	User::LeaveIfError(CreateDrive(Drive().DriveNumber()));
       
   298 
       
   299     //-- read FAT configuration parameters from estart.txt
       
   300     iFatConfig.ReadConfig(driveNo);
       
   301 
       
   302 
       
   303     //-- initialise interface to the low-level drive access
       
   304     if(!iDriverInterface.Init(this))
       
   305         User::LeaveIfError(KErrNoMemory);    
       
   306 
       
   307 	//-- get drive capabilities
       
   308     TLocalDriveCapsV2Buf capsBuf;
       
   309 	User::LeaveIfError(LocalDrive()->Caps(capsBuf));
       
   310 	
       
   311     iSize=capsBuf().iSize;
       
   312     iRamDrive = EFalse;
       
   313 
       
   314     if(capsBuf().iMediaAtt & KMediaAttVariableSize)
       
   315     {//-- this is a RAM drive
       
   316 		UserSvr::UnlockRamDrive();
       
   317         iRamDrive = ETrue;
       
   318 	}
       
   319 
       
   320 	if(aForceMount)
       
   321 	{//-- the state is "forcedly mounted", special case. This is an inconsistent state.
       
   322         SetState(EInit_Forced);  
       
   323     	return;
       
   324     }
       
   325 
       
   326     //-- read and validate boot sector (sector 0)
       
   327     TFatBootSector bootSector;
       
   328     User::LeaveIfError(ReadBootSector(bootSector, iRamDrive));
       
   329 
       
   330     //-- print out boot sector debug information
       
   331     bootSector.PrintDebugInfo();
       
   332 
       
   333 	//-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt
       
   334     iFatType=bootSector.FatType();
       
   335     ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector()
       
   336 
       
   337     //-- values from the boot sector are checked in TFatBootSector::IsValid()
       
   338     //-- store volume UID, it can be checked on Remount
       
   339     iUniqueID = bootSector.UniqueID();
       
   340 
       
   341     //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid()
       
   342     iVolParam.Populate(bootSector); 
       
   343 
       
   344     //-- initialize the volume
       
   345     InitializeL(capsBuf());
       
   346     ASSERT(State()==EInit_R);
       
   347 
       
   348     GetVolumeLabelFromDiskL(bootSector);
       
   349 
       
   350 	__PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State());
       
   351 	}
       
   352 
       
   353 
       
   354 
       
   355 //-------------------------------------------------------------------------------------------------------------------
       
   356 
       
   357 /**
       
   358 Initialize the FAT cache and disk access
       
   359 
       
   360 @param  aLocDrvCaps local drive capabilities
       
   361 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
       
   362 */
       
   363 void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool /*aIgnoreFSInfo=EFalse*/)
       
   364 	{
       
   365     __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber());
       
   366 
       
   367     ASSERT(State() == EMounting); //-- we must get here only from MountL()
       
   368 
       
   369     //========== Find out number of clusters on the volume
       
   370 	if(iRamDrive && SectorsPerCluster()!=1)
       
   371 		{// Align iFirstFreeByte to cluster boundary if internal ram drive
       
   372 		const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2();
       
   373 		const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2();
       
   374 		const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2;
       
   375 		iFirstFreeByte=alignedSector<<SectorSizeLog2();
       
   376 		}
       
   377 	else
       
   378 		{
       
   379 		iFirstFreeByte=RootDirEnd();
       
   380 		}
       
   381 
       
   382 
       
   383 	    {//-- check if volume geometry looks valid
       
   384 	    const TInt usableSectors=TotalSectors()-(iFirstFreeByte>>SectorSizeLog2());
       
   385 	    iUsableClusters=usableSectors>>(ClusterSizeLog2()-SectorSizeLog2());
       
   386 
       
   387         const TUint32 KMinClusters = 32; //-- absolute minimum number of clusters on the volume
       
   388         const TUint32 KMaxClusters =(TotalSectors()-FirstFatSector()-NumberOfFats()*(FatSizeInBytes()>>SectorSizeLog2())) >> (ClusterSizeLog2()-SectorSizeLog2());
       
   389         
       
   390         if(usableSectors <=0 || iUsableClusters < KMinClusters || iUsableClusters > KMaxClusters)
       
   391             {
       
   392             __PRINT(_L("CFatMountCB::InitializeL() Wrong number of usable cluster/sectors on the volume!"));
       
   393             User::Leave(KErrCorrupt);
       
   394             }
       
   395         }
       
   396 
       
   397 
       
   398 	//========== initialise RawDisk interface
       
   399 	//-- CFatMountCB parameters might have changed, e.g. after formatting. Reconstruct directory cache with new parameters
       
   400 	
       
   401     delete iRawDisk;
       
   402 	iRawDisk=CRawDisk::NewL(*this, aLocDrvCaps);
       
   403     iRawDisk->InitializeL();
       
   404     
       
   405 
       
   406     //========== create FAT table object
       
   407 	delete iFatTable;
       
   408 	iFatTable=CFatTable::NewL(*this, aLocDrvCaps);
       
   409 
       
   410     //========== create and setup leaf direcotry cache if cache limit is set bigger than one 
       
   411 	const TUint32 cacheLimit = iFatConfig.LeafDirCacheSize();
       
   412 	if (cacheLimit > 1)
       
   413 		{
       
   414 		// destroy the old leaf dir cache to avoid memory leak.
       
   415 		delete iLeafDirCache;
       
   416 		iLeafDirCache = CLeafDirCache::NewL(cacheLimit);
       
   417 		}
       
   418 	else
       
   419 		{
       
   420 		iLeafDirCache = NULL;
       
   421 		}
       
   422 
       
   423     //==========  find out free clusters number on the volume
       
   424     FAT().CountFreeClustersL();
       
   425     
       
   426     SetState(EInit_R);  //-- the state is "Initialized, but not writen"
       
   427 
       
   428     //-- make a callback, telling FileServer about free space discovered.
       
   429     const TInt64 freeSpace = ((TInt64)FAT().NumberOfFreeClusters()) << ClusterSizeLog2();
       
   430     SetDiskSpaceChange(freeSpace);
       
   431 
       
   432     __PRINT3(_L("#- CFatMountCB::InitializeL() done. drv:%d, Free clusters:%d, 1st Free cluster:%d"),DriveNumber(), FAT().NumberOfFreeClusters(), FAT().FreeClusterHint());
       
   433 	}
       
   434 
       
   435 //-------------------------------------------------------------------------------------------------------------------
       
   436 
       
   437 
       
   438 
       
   439 /**
       
   440 Checks for end of file for all Fat types
       
   441 
       
   442 @param aCluster Cluster to check
       
   443 @return Result of test
       
   444 */
       
   445 TBool CFatMountCB::IsEndOfClusterCh(TInt aCluster) const
       
   446 	{
       
   447 	if(Is16BitFat())
       
   448 		return(aCluster>=0xFFF8 && aCluster<=0xFFFF);
       
   449 	else
       
   450 		return(aCluster>=0xFF8 && aCluster<=0xFFF);
       
   451 	}
       
   452 
       
   453 /**
       
   454 Set a cluster to the end of cluster chain marker
       
   455 
       
   456 @param aCluster cluster to set to end of chain marker
       
   457 */
       
   458 void CFatMountCB::SetEndOfClusterCh(TInt &aCluster) const
       
   459 	{
       
   460 	if(Is16BitFat())
       
   461 		aCluster=0xFFF8;
       
   462 	else
       
   463 		aCluster=0xFF8;
       
   464 	}
       
   465 
       
   466 /**
       
   467 Initialize data to represent the root directory
       
   468 
       
   469 @param anEntry Entry to initialise
       
   470 */
       
   471 void CFatMountCB::InitializeRootEntry(TFatDirEntry & anEntry) const
       
   472 	{
       
   473 	anEntry.SetName(_L8("ROOT"));
       
   474 	anEntry.SetAttributes(KEntryAttDir);
       
   475 	anEntry.SetStartCluster(0);		
       
   476 	}
       
   477 
       
   478 
       
   479 /**
       
   480 Implementation of CMountCB::FileSystemSubType(). Retrieves the sub type of Fat file system
       
   481 and returns the name as a descriptor.
       
   482 
       
   483 @param aName Name of the sub type of Fat file system
       
   484 @return KErrNone if successful; KErrArgument if aName is not long enough; KErrNotReady if
       
   485 		the mount is not ready.
       
   486 
       
   487 @see CMountCB::FileSystemSubType()
       
   488 */
       
   489 TInt CFatMountCB::SubType(TDes& aName) const
       
   490 	{
       
   491 	if(aName.MaxLength() < 5)
       
   492 		return KErrArgument;
       
   493 	
       
   494 	switch (iFatType)
       
   495 		{
       
   496 		case EFat12:
       
   497 			{
       
   498 			aName = KFSSubType_FAT12;
       
   499 			return KErrNone;
       
   500 			}
       
   501 		case EFat16:
       
   502 			{
       
   503 			aName = KFSSubType_FAT16;
       
   504 			return KErrNone;
       
   505 			}
       
   506 		default:
       
   507 		// case EInvalidFatType
       
   508 			return KErrNotReady;
       
   509 		}
       
   510 	}
       
   511 
       
   512 //-------------------------------------------------------------------------------------------------------------------
       
   513 /**
       
   514     CFatMountCB control method.
       
   515     @param  aLevel  specifies the operation to perfrom on the mount
       
   516     @param  aOption specific option for the given operation
       
   517     @param  aParam  pointer to generic parameter, its meaning depends on aLevel and aOption
       
   518 
       
   519     @return standard error code.
       
   520 */
       
   521 TInt CFatMountCB::MountControl(TInt aLevel, TInt aOption, TAny* aParam)
       
   522     {
       
   523     TInt nRes = KErrNotSupported; 
       
   524 
       
   525     if(aLevel == ECheckFsMountable)
       
   526         {
       
   527         return MntCtl_DoCheckFileSystemMountable();
       
   528         }
       
   529     
       
   530     //-- mount state query: check if is in finalised state 
       
   531     if(aLevel == EMountStateQuery && aOption == ESQ_IsMountFinalised)
       
   532         {
       
   533         TBool bFinalised;
       
   534         nRes = IsFinalised(bFinalised);
       
   535         if(nRes == KErrNone)
       
   536             {
       
   537             *((TBool*)aParam) = bFinalised;
       
   538             }
       
   539         
       
   540         return nRes;
       
   541         }
       
   542 
       
   543     //-- File System - specific queries 
       
   544     if(aLevel == EMountFsParamQuery && aOption == ESQ_GetMaxSupportedFileSize)
       
   545         {//-- this is a query to provide the max. supported file size; aParam is a pointer to TUint64 to return the value
       
   546         *(TUint64*)aParam = KMaxSupportedFatFileSize;    
       
   547         return KErrNone;
       
   548         }
       
   549 
       
   550 
       
   551     return nRes;
       
   552     }
       
   553 
       
   554 //-------------------------------------------------------------------------------------------------------------------
       
   555 /**
       
   556 Reports whether the specified interface is supported - if it is,
       
   557 the supplied interface object is modified to it
       
   558 
       
   559 @param aInterfaceId     The interface of interest
       
   560 @param aInterface       The interface object
       
   561 @return                 KErrNone if the interface is supported, otherwise KErrNotFound 
       
   562 
       
   563 @see CMountCB::GetInterface()
       
   564 */
       
   565 TInt CFatMountCB::GetInterface(TInt aInterfaceId, TAny*& aInterface,TAny* aInput)
       
   566     {
       
   567     switch(aInterfaceId)
       
   568         {
       
   569         case (CMountCB::EFileAccessor):
       
   570             ((CMountCB::MFileAccessor*&) aInterface) = this;
       
   571             return KErrNone;
       
   572         
       
   573         case (CMountCB::EGetFileSystemSubType):
       
   574             aInterface = (MFileSystemSubType*) (this);
       
   575             return KErrNone;
       
   576 
       
   577         case (CMountCB::EGetClusterSize):
       
   578             aInterface = (MFileSystemClusterSize*) (this);
       
   579             return KErrNone;
       
   580 
       
   581         case CMountCB::ELocalBufferSupport:
       
   582             // RAM drives doesn't support local buffers (this results in file caching being disabled)
       
   583             if (iRamDrive) 
       
   584                 return KErrNotSupported;
       
   585             else
       
   586                 return LocalDrive()->LocalBufferSupport();
       
   587 
       
   588 		case EGetProxyDrive:
       
   589 			((CProxyDrive*&)aInterface) = LocalDrive();
       
   590 			return KErrNone;
       
   591         
       
   592         default:
       
   593             return(CMountCB::GetInterface(aInterfaceId, aInterface, aInput));
       
   594         }
       
   595     }
       
   596