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