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