userlibandfileserver/fileserver/sfat/sl_mnt16.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9: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_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