userlibandfileserver/fileserver/automounter/automounter.cpp
changeset 0 a41df078684a
child 33 0173bcd7697c
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1998-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 
       
    15 /**
       
    16 @file
       
    17 @internalTechnology
       
    18 */
       
    19 
       
    20 #include <e32cmn.h>
       
    21 #include <f32ver.h>
       
    22 #include <u32std.h>
       
    23 #include <f32file.h>
       
    24 
       
    25 
       
    26 
       
    27 #include "filesystem_automounter.h"
       
    28 #include "automounter.h"
       
    29 
       
    30 
       
    31 //-----------------------------------------------------------------------------
       
    32 
       
    33 void Fault(TFault aFault)
       
    34     {
       
    35     _LIT(KPanicName, "AutoMounter_fsy");
       
    36     User::Panic(KPanicName, aFault);
       
    37     }
       
    38 
       
    39 
       
    40 //-----------------------------------------------------------------------------
       
    41 
       
    42 /**
       
    43     Factory function, Create a new object of this file system 
       
    44 */
       
    45 extern "C" 
       
    46 {
       
    47 EXPORT_C CFileSystem* CreateFileSystem()
       
    48     {
       
    49     return CAutoMounterFileSystem::New();
       
    50     }
       
    51 }
       
    52 
       
    53 
       
    54 //#######################################################################################################################################
       
    55 //#  CAutoMounterFileSystem class implementation
       
    56 //#######################################################################################################################################
       
    57 
       
    58 /**
       
    59     Factory method
       
    60 */
       
    61 CAutoMounterFileSystem* CAutoMounterFileSystem::New()
       
    62     {
       
    63     CAutoMounterFileSystem* pThis = new CAutoMounterFileSystem();
       
    64     return pThis;
       
    65     }
       
    66 
       
    67 
       
    68 CAutoMounterFileSystem::CAutoMounterFileSystem() 
       
    69     {
       
    70     __PRINT1(_L("#<<- CAutoMounterFileSystem::CAutoMounterFileSystem() [0x%x]"), this);
       
    71 
       
    72     SetState(EInvalid);
       
    73     }   
       
    74 
       
    75 CAutoMounterFileSystem::~CAutoMounterFileSystem()
       
    76     {
       
    77     __PRINT1(_L("#<<- CAutoMounterFileSystem::~CAutoMounterFileSystem() [0x%x]"), this);
       
    78     }
       
    79 
       
    80 //-----------------------------------------------------------------------------
       
    81 
       
    82 /**
       
    83     Install iand initialise file system.
       
    84 */
       
    85 TInt CAutoMounterFileSystem::Install()
       
    86     {
       
    87    
       
    88     SetState(ENotInitialised);
       
    89 
       
    90     __PRINT1(_L("#<<- CAutoMounterFileSystem::Install() [0x%x]"), this);
       
    91 
       
    92     iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber);
       
    93 
       
    94     InitialiseFileSystem();
       
    95 
       
    96     return SetName(&KFileSystemName_AutoMounter);
       
    97     }
       
    98 
       
    99 
       
   100 //-----------------------------------------------------------------------------
       
   101 /** 
       
   102     Create a new mount control block. 
       
   103     This method migh be called by the file server in some unusual cases, when the actual mount is needed only temporarily to get access to the 
       
   104     corresponding media driver. E.g. TDrive::ForceRemountDrive()
       
   105     Produce the _default_ file system mount
       
   106 */
       
   107 CMountCB* CAutoMounterFileSystem::NewMountL() const
       
   108     {
       
   109     __PRINT1(_L("#<<- CAutoMounterFileSystem::NewMountL() [0x%x]"), this);
       
   110     ASSERT(State() == EInitialised);
       
   111 
       
   112     __PRINT1(_L("#<<- producing the _default_ filesystem:%S"), &iFSNames[KDefaultFSNo]);
       
   113 
       
   114     CFileSystem* pFS = GetChildFileSystem(KDefaultFSNo);
       
   115     ASSERT(pFS);
       
   116 
       
   117     return pFS->NewMountL();
       
   118     }
       
   119 
       
   120 //-----------------------------------------------------------------------------
       
   121 /** 
       
   122     Create a new file. 
       
   123 */
       
   124 CFileCB* CAutoMounterFileSystem::NewFileL() const
       
   125     {
       
   126     __PRINT1(_L("#<<- CAutoMounterFileSystem::NewFileL() [0x%x]"), this);
       
   127     Fault(EMustNotBeCalled);
       
   128     return NULL;
       
   129     }
       
   130 
       
   131 //-----------------------------------------------------------------------------
       
   132 /** 
       
   133     Create a new directory object 
       
   134 */
       
   135 CDirCB* CAutoMounterFileSystem::NewDirL() const
       
   136     {
       
   137     __PRINT1(_L("#<<- CAutoMounterFileSystem::NewDirL() [0x%x]"), this);
       
   138     Fault(EMustNotBeCalled);
       
   139     return NULL;
       
   140     }
       
   141 
       
   142 //-----------------------------------------------------------------------------
       
   143 /** 
       
   144     Create a new media formatter 
       
   145 */
       
   146 CFormatCB* CAutoMounterFileSystem::NewFormatL() const
       
   147     {
       
   148     __PRINT1(_L("#<<- CAutoMounterFileSystem::NewFormatL() [0x%x]"), this);
       
   149     Fault(EMustNotBeCalled);
       
   150     return NULL;
       
   151     }
       
   152 
       
   153 //-----------------------------------------------------------------------------
       
   154 /** 
       
   155     Return the drive info
       
   156 */
       
   157 void CAutoMounterFileSystem::DriveInfo(TDriveInfo& anInfo,TInt aDriveNumber) const
       
   158     {
       
   159     //!!!!!!!!!!!! This method shall be made the same as FAT, exFAT etc. 
       
   160     //!! General idea: make all this code common for all filesystems and put it into the file server
       
   161     //!! The problem: need to have another exported method. Actually, the generic code can be placed to CFileSystem::DriveInfo()
       
   162     //!! despite it a pure virtual. 
       
   163 
       
   164     __PRINT1(_L("#<<- CAutoMounterFileSystem::DriveInfo() [0x%x]"), this);
       
   165 
       
   166     if(!IsValidLocalDriveMapping(aDriveNumber))
       
   167         return;
       
   168 
       
   169     TLocalDriveCapsV2Buf localDriveCaps;
       
   170     
       
   171     TInt r = KErrNone;
       
   172 
       
   173     // is the drive local?
       
   174     if (!IsProxyDrive(aDriveNumber))
       
   175         {
       
   176         // if not valid local drive, use default values in localDriveCaps
       
   177         // if valid local drive and not locked, use TBusLocalDrive::Caps() values
       
   178         // if valid drive and locked, hard-code attributes
       
   179         r = GetLocalDrive(aDriveNumber).Caps(localDriveCaps);
       
   180         }
       
   181     else  // this need to be made a bit nicer
       
   182         {   
       
   183         CExtProxyDrive* pD = GetProxyDrive(aDriveNumber);
       
   184         if(pD)
       
   185             r = pD->Caps(localDriveCaps);
       
   186         else
       
   187             r = KErrNotReady;   // What should the behaviour really be here?
       
   188         }
       
   189 
       
   190     if (r != KErrLocked )
       
   191         {
       
   192         anInfo.iMediaAtt=localDriveCaps().iMediaAtt;
       
   193         }
       
   194     else
       
   195         {
       
   196         anInfo.iMediaAtt = KMediaAttLocked | KMediaAttLockable | KMediaAttHasPassword;
       
   197         }
       
   198 
       
   199     anInfo.iType=localDriveCaps().iType;
       
   200     anInfo.iDriveAtt=localDriveCaps().iDriveAtt;
       
   201     }
       
   202 
       
   203 //-----------------------------------------------------------------------------
       
   204 
       
   205 #ifdef _DEBUG
       
   206 /**
       
   207     Called by File Server before deleting File System object.    
       
   208 */
       
   209 TInt CAutoMounterFileSystem::Remove()
       
   210     {
       
   211     __PRINT1(_L("#<<- CAutoMounterFileSystem::Remove() [0x%x]"), this);
       
   212     return CFileSystem::Remove();
       
   213     }
       
   214 
       
   215 //-----------------------------------------------------------------------------
       
   216 
       
   217 /**
       
   218 */
       
   219 TBool CAutoMounterFileSystem::QueryVersionSupported(const TVersion& aVer) const
       
   220     {
       
   221     __PRINT1(_L("#<<- CAutoMounterFileSystem::QueryVersionSupported() [0x%x]"), this);
       
   222     return CFileSystem::QueryVersionSupported(aVer);
       
   223     }
       
   224 
       
   225 #endif
       
   226 
       
   227 //-----------------------------------------------------------------------------
       
   228 
       
   229 /**
       
   230     Find out if drive extensions are supported. In order to have consistent behaviour, _all_ child 
       
   231     file systems shall behave the same way.   
       
   232     
       
   233     @return ETrue if drive extensions are supported.    
       
   234 */
       
   235 TBool CAutoMounterFileSystem::IsExtensionSupported() const
       
   236     {
       
   237     __PRINT1(_L("#<<- CAutoMounterFileSystem::IsExtensionSupported() [0x%x]"), this);
       
   238     
       
   239     ASSERT(State() == EInitialised && iFSNames.Count() > 1);
       
   240 
       
   241 
       
   242     //-- in debug mode check file systems compatibility: ALL childs must support this feature
       
   243     for(TUint i=0; i<iFSNames.Count(); ++i)
       
   244         {
       
   245         if( !(GetChildFileSystem(i)->IsExtensionSupported()))
       
   246             {
       
   247             DBG_STATEMENT(Fault(EIncompatibleFileSystems));
       
   248             __PRINT(_L("#<<- ::IsExtensionSupported(): Incompatible file sytems!"));
       
   249             return EFalse;
       
   250             }
       
   251         }
       
   252 
       
   253 
       
   254     return ETrue; 
       
   255     }
       
   256 
       
   257 //-----------------------------------------------------------------------------
       
   258 
       
   259 /** 
       
   260     Return the initial default path. 
       
   261 */
       
   262 TInt CAutoMounterFileSystem::DefaultPath(TDes& aPath) const
       
   263     {
       
   264     __PRINT1(_L("#<<- CAutoMounterFileSystem::DefaultPath() [0x%x]"), this);
       
   265 
       
   266     aPath=_L("?:\\");
       
   267     aPath[0] = (TUint8) RFs::GetSystemDriveChar();
       
   268     return KErrNone;
       
   269     }
       
   270 
       
   271 
       
   272 //-----------------------------------------------------------------------------
       
   273 
       
   274 /**
       
   275     Additional interfaces support.    
       
   276 */
       
   277 TInt CAutoMounterFileSystem::GetInterface(TInt aInterfaceId, TAny*& aInterface, TAny* aInput)
       
   278     {
       
   279 
       
   280     __PRINT2(_L("#<<- CAutoMounterFileSystem::GetInterface(id:%d) [0x%x]"), aInterfaceId, this);
       
   281 
       
   282     switch(aInterfaceId)
       
   283         {
       
   284         //-- It is this filesystem private interface.
       
   285         case EExtendedFunctionality:
       
   286         aInterface = (CFileSystem::MFileSystemExtInterface*)this;
       
   287         return KErrNone;
       
   288         
       
   289         //-- a special case for child filesystems.
       
   290         //-- ALL of them must respond to this interface query exactly the same way. I.e. It is impossible
       
   291         //-- to have some of the child FS supporting it and some not.
       
   292         case EProxyDriveSupport:
       
   293         return DoProcessProxyDriveSupport();
       
   294 
       
   295 
       
   296         default:
       
   297         //-- This is the request to other (child file system) from the file server
       
   298         //-- Actually, this part must never be called. File Server shall query the file system interfaces _after_ mounting the concrete FS 
       
   299         //-- calling TDrive::iCurrentMount->FileSystem().GetInterface() 
       
   300         ASSERT(0);
       
   301         return CFileSystem::GetInterface(aInterfaceId, aInterface, aInput);
       
   302         
       
   303         }
       
   304     }
       
   305 
       
   306 //-----------------------------------------------------------------------------
       
   307 /**
       
   308     @return Boolean exclusive OR between a1 and a2
       
   309 */
       
   310 TBool BoolXOR(TBool a1, TBool a2)
       
   311     {
       
   312     if(!a1 && !a2)        
       
   313         return EFalse;
       
   314     else if(a1 && a2)
       
   315         return EFalse;
       
   316     else
       
   317         return ETrue;
       
   318     }
       
   319 
       
   320 //-----------------------------------------------------------------------------
       
   321 
       
   322 /**
       
   323     Find out if _all_ child file systems support the proxy drive. All childs shall behave exactly the same way.
       
   324     @return KErrNone if all child file systems support proxy drives, or KErrNotSupported if all of them do not.
       
   325 */
       
   326 TInt CAutoMounterFileSystem::DoProcessProxyDriveSupport()
       
   327     {
       
   328     __PRINT1(_L("#<<- CAutoMounterFileSystem::DoProcessProxyDriveSupport[0x%x]"), this);
       
   329     ASSERT(State() == EInitialised);
       
   330 
       
   331     const TUint cnt = iFSNames.Count();
       
   332     ASSERT(cnt > 1);
       
   333 
       
   334     
       
   335     //-- query the default filesystem #0
       
   336     const TBool bRes = GetChildFileSystem(KDefaultFSNo)->IsProxyDriveSupported();
       
   337 
       
   338     //-- query the rest of child filesystems
       
   339     for(TUint i=1; i<cnt; ++i)
       
   340         {
       
   341         const TBool b = GetChildFileSystem(i)->IsProxyDriveSupported();
       
   342 
       
   343         if(BoolXOR(b, bRes))
       
   344             Fault(EIncompatibleFileSystems);
       
   345         }
       
   346 
       
   347 
       
   348     return  bRes ? KErrNone : KErrNotSupported;
       
   349     }
       
   350 
       
   351 //-----------------------------------------------------------------------------
       
   352 /**
       
   353     Get the child file system name by its index (enumerator).
       
   354     
       
   355     @param  aFsNumber   index of the child FS 0...KMaxTInt
       
   356     @param  aFsName     on success the child file system name will be placed into this buffer  
       
   357 
       
   358     @return KErrNone        if there is a child FS name with index 'aFsNumber' (child FS 'aFsNumber' is supported by automounter)
       
   359             KErrNotFound    if child FS 'aFsNumber' is not supported
       
   360 */
       
   361 TInt CAutoMounterFileSystem::GetSupportedFileSystemName(TInt aFsNumber, TDes& aFsName) const
       
   362     {
       
   363     __PRINT2(_L("#<<- CAutoMounterFileSystem::GetSupportedFileSystemName[0x%x](%d)"), this, aFsNumber);
       
   364 
       
   365     if(aFsNumber == RFs::KRootFileSystem)
       
   366         {//-- this is a name query for "root filesystem" or automounter
       
   367         aFsName = Name(); //-- ourselves
       
   368         return KErrNone;
       
   369         }
       
   370     
       
   371     //-- this is a query for one of the child filesystems
       
   372     if((TUint)aFsNumber < iFSNames.Count())
       
   373         {
       
   374         aFsName = iFSNames[aFsNumber]; 
       
   375         return KErrNone;
       
   376         }
       
   377 
       
   378     
       
   379     return KErrNotFound;
       
   380     }
       
   381 
       
   382 
       
   383 //-----------------------------------------------------------------------------
       
   384 /**
       
   385     This is the only factory method that can be called by file server for this file system.
       
   386     In this method the automounter sequentially tries to mount every child and on success produces the corresponding CMountCB object.
       
   387 
       
   388     @param  apDrive         pointer to the TDrive, child FS will need this to access media.
       
   389     @param  apFileSystem    on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if 
       
   390                             one of the child file system has recognised the volume.
       
   391     @param  aForceMount     if ETrue the appropriate child FS (designated by aFsNameHash) will be forcedly mounted on the volume. for volume formatting purposes.
       
   392     @param  aFsNameHash     if !=0 specifies the file system name, see TVolFormatParam::CalcFSNameHash(). 0 means "file system name is not specified"
       
   393 
       
   394     @return pointer to the constructed CMountCB by one of the child file systems (and pointer to this child FS in apFileSystem)
       
   395             NULL if it was impossible to produce proper CMountCB object.
       
   396 
       
   397 */
       
   398 CMountCB* CAutoMounterFileSystem::NewMountExL(TDrive* apDrive, CFileSystem** apFileSystem, TBool aForceMount, TUint32 aFsNameHash)
       
   399     {
       
   400     __PRINT4(_L("#<<- CAutoMounterFileSystem::NewMountExL[0x%x] drv:%d, ForceMount:%d, FSNameHash:0x%x"), this, apDrive->DriveNumber(), aForceMount, aFsNameHash);
       
   401 
       
   402     ASSERT(State() == EInitialised && apDrive);
       
   403 
       
   404     //-- This method is usually called from the appropriate drive thread; this file system is intended to be bound to
       
   405     //-- removable drives. Having removable drive runnind in the main file server thread means that something is terribly wrongly configured.
       
   406     if(apDrive->IsSynchronous())
       
   407         Fault(EWrongDriveAttributes);
       
   408 
       
   409     if(iFSNames.Count() < 2)
       
   410         Fault(EWrongConfiguration);
       
   411 
       
   412 
       
   413     //-- if aForceMount is true, this means that the TDrive tries mount the filesystem by force for formatting because normal mounting has failed before. 
       
   414     //-- in our case it means that the file system on the volume hadn't been recognised by any child FS.
       
   415     //-- aFsNameHash shall designate the file system to be forcedly mounted. Depending on this the appropriat CMounCB object will be produced.
       
   416     //-- if aFsNameHash is 0, i.e. not provided, this method will fail with KErrNotFound because it is impossible to select appropriat child FS.
       
   417     if(aForceMount)
       
   418         {
       
   419         if(aFsNameHash == 0)
       
   420             {//-- the file system to mount forcedly is not specified
       
   421             __PRINT(_L("#<<- Unable to select appropriate child FS for formatting!"));
       
   422             User::Leave(KErrNotFound);
       
   423             }
       
   424         else
       
   425             {//-- try to find appropriate child FS by its name hash
       
   426             CFileSystem *pFS = GetChildFileSysteByNameHash(aFsNameHash);
       
   427             if(!pFS)
       
   428                 {
       
   429                 __PRINT(_L("#<<- no child FS found by its name hash!"));
       
   430                 ASSERT(0);
       
   431                 User::Leave(KErrNotFound);
       
   432                 }
       
   433 
       
   434             CMountCB* pMount = pFS->NewMountL();
       
   435             ASSERT(pMount);
       
   436 
       
   437             *apFileSystem = pFS; 
       
   438             return pMount;
       
   439             }
       
   440         }//if(aForceMount)
       
   441 
       
   442 
       
   443 
       
   444     //-- try instantiate a new CMountCB depending on the file system on the media
       
   445 
       
   446     CMountCB* pMatchedMount;
       
   447     TInt nRes = TryMountFilesystem(apDrive, &pMatchedMount, apFileSystem);
       
   448     
       
   449     if(nRes == KErrNone)
       
   450         {
       
   451         ASSERT(pMatchedMount);
       
   452         return pMatchedMount;
       
   453         }
       
   454 
       
   455 
       
   456 
       
   457     User::Leave(nRes);
       
   458     return NULL;
       
   459     }
       
   460 
       
   461 //-----------------------------------------------------------------------------
       
   462 /**
       
   463     Initialise this file system. Reads and processes configuration, fills in file system names container, etc. 
       
   464 */
       
   465 void CAutoMounterFileSystem::InitialiseFileSystem()
       
   466     {
       
   467     __PRINT1(_L("#<<- CAutoMounterFileSystem::InitialiseFileSystem() [0x%x]"), this);
       
   468 
       
   469     ASSERT(State() == ENotInitialised);
       
   470 
       
   471     TInt nRes;
       
   472     
       
   473 
       
   474     //-- 1. initialise the array of file system names. These names shall be listed in a config string.
       
   475     //-- the config string is taken from estart.txt usually and its format is like this: 
       
   476     //-- section: [AutoMounter] and property "FSNames fat,exfat"
       
   477     //-- in debug version a special text property can override the config string. This allows controlling automounter from
       
   478     //-- the test environment.
       
   479 
       
   480     TBuf8<0x100> buf(0);   
       
   481     TBuf<0x100>  fsName;   
       
   482 
       
   483 
       
   484 #ifdef _DEBUG
       
   485     const TUid KSID_Test1={0x10210EB3}; //-- SID of the test that will define and set test property to control volume mounting
       
   486     const TUint KPropKey = 0; //-- property key
       
   487 
       
   488     //-- in debug mode the property will override the estart.txt config
       
   489     if(RProperty::Get(KSID_Test1, KPropKey, buf) == KErrNone)
       
   490         {
       
   491         __PRINT(_L("#<<- reading config from the debug propery..."));
       
   492         }
       
   493     else
       
   494 #endif
       
   495         {
       
   496         __PRINT(_L("#<<- reading config from estart.txt..."));
       
   497         _LIT8(KSection,  "AutoMounter");
       
   498         _LIT8(KProperty, "FSNames");
       
   499 
       
   500         nRes = F32Properties::GetString(KSection, KProperty, buf);
       
   501         if(!nRes)
       
   502             Fault(EPluginInitialise);
       
   503         }
       
   504 
       
   505 
       
   506     fsName.Copy(buf);
       
   507     __PRINT1(_L("#<<- config:'%S'"), &fsName);
       
   508 
       
   509     //-- parse CSV config line and fill in the file system names array
       
   510     const TChar chDelim = ','; //-- token delimiter, comma
       
   511     buf.Trim();
       
   512     TPtrC8 ptrCurrLine(buf);
       
   513     for(TInt i=0; ;++i)
       
   514         {
       
   515         const TInt delimPos = ptrCurrLine.Locate(chDelim);
       
   516         if(delimPos <= 0)
       
   517             {
       
   518             fsName.Copy(ptrCurrLine);
       
   519             }
       
   520         else
       
   521             {
       
   522             TPtrC8 temp(ptrCurrLine.Ptr(), delimPos);
       
   523             fsName.Copy(temp);
       
   524             }
       
   525 
       
   526         fsName.Trim();
       
   527         __PRINT2(_L("#<<- child FS[%d]: '%S'"), i, &fsName);
       
   528 
       
   529         
       
   530         if(fsName.Length() <= 0) 
       
   531             Fault(EPluginInitialise);
       
   532 
       
   533         //-- check if the FS name being appended is unique
       
   534         for(TUint j=0; j<iFSNames.Count(); ++j)
       
   535             {
       
   536             if(iFSNames[j] == fsName)
       
   537                 {
       
   538                 Fault(EPluginInitialise);
       
   539                 }
       
   540             }
       
   541         
       
   542         
       
   543         nRes = iFSNames.Append(fsName);
       
   544         ASSERT(nRes ==KErrNone);
       
   545         
       
   546         if(delimPos <=0 )
       
   547             break;
       
   548 
       
   549         ptrCurrLine.Set(ptrCurrLine.Ptr()+delimPos+1, ptrCurrLine.Length()-delimPos-1);
       
   550         }
       
   551 
       
   552 
       
   553     SetState(EInitialised);
       
   554 
       
   555     //-- 2. check that the file server has all filesystems we need instantiated and stored in a global container
       
   556     TUint cnt = iFSNames.Count();
       
   557     if(cnt < 2)
       
   558         {
       
   559         __PRINT(_L("#<<- ::InitialiseFileSystem(): too few File Systems bound!"));
       
   560         Fault(EPluginInitialise);
       
   561         }
       
   562 
       
   563     while(cnt--)
       
   564         {
       
   565         GetChildFileSystem(cnt);
       
   566         }
       
   567 
       
   568 
       
   569     }
       
   570 
       
   571 
       
   572 
       
   573 //-----------------------------------------------------------------------------
       
   574 /**
       
   575     Tries to find out if some of the child file systems can be mounted on the given volume.
       
   576 
       
   577     @param  apDrive         pointer to the TDrive, child FS will need this to access media.
       
   578     @param                  on return will contain the pointer to the CMountCB object if some of the childs has decided that it can be mounted.
       
   579     @param  apFS            on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if 
       
   580 
       
   581     @return KErrNone on success, otherwise standard error code.
       
   582 
       
   583 */
       
   584 TInt CAutoMounterFileSystem::TryMountFilesystem(TDrive* apDrive, CMountCB** apMount, CFileSystem** apFS)
       
   585     {
       
   586     __PRINT1(_L("#<<- CAutoMounterFileSystem::TryMountFilesystem()[0x%x]"), this);
       
   587 
       
   588     const TInt KNumFS = iFSNames.Count();
       
   589   
       
   590     ASSERT(State() == EInitialised && (KNumFS >1));
       
   591 
       
   592 
       
   593     *apMount = NULL;
       
   594     *apFS    = NULL;
       
   595     
       
   596     
       
   597     TInt nRes;
       
   598     TInt cntFS;
       
   599     CMountCB*       pMountCB = NULL;
       
   600     CFileSystem*    pMatchedFS = NULL;
       
   601 
       
   602     for(cntFS=0; cntFS < KNumFS; ++cntFS)
       
   603         {
       
   604 
       
   605         __PRINT2(_L("#<<-@@ trying FS[%d]:%S"), cntFS, &iFSNames[cntFS]);
       
   606 
       
   607         CFileSystem* pFS = GetChildFileSystem(cntFS); //-- Find current filesystem object in the FileServer's global container
       
   608 
       
   609         //-- 2. create CMountCB instance and set it up
       
   610         pMountCB = NULL;
       
   611         
       
   612         TRAP(nRes, pMountCB = pFS->NewMountL());
       
   613         if(nRes != KErrNone)
       
   614             {
       
   615             return KErrNoMemory;
       
   616             }
       
   617 
       
   618         ASSERT(pMountCB);
       
   619         pMountCB->SetDrive(apDrive);
       
   620 
       
   621         
       
   622         //-- 2.1 Firstly try using special CMountCB interface to find out if current FS can be mounted on this media
       
   623         nRes = pMountCB->CheckFileSystemMountable();
       
   624         if(nRes == KErrNotSupported)
       
   625             {
       
   626             //-- file system doesn't support this feature,
       
   627             //-- 2.2 try to check the file system by mounting and dismounting later. It can result in some long activity, like FAT scanning etc.
       
   628             TRAP(nRes, pMountCB->MountL(EFalse));
       
   629             pMountCB->Dismounted(); //-- dismount the mountCB, it will be required in dismounted state anyway 
       
   630             }
       
   631         
       
   632         //-- 2.3 analyse the result of mounting 
       
   633         if(nRes != KErrNone)
       
   634             {
       
   635             if(nRes == KErrLocked)
       
   636                 {//-- this is a special case; The media (SD card for example) is locked. 
       
   637                 //-- Pretend that everything is OK and return CMountCB instance that is produced by the _default_ file system.
       
   638                 //-- locked media case will be handled by the file server later.
       
   639                 ASSERT(cntFS == KDefaultFSNo); //-- the default FS is tried first and must detect the locked media
       
   640                 pMatchedFS = pFS;
       
   641                 __PRINT(_L("#<<-@@ The media is LOCKED !"));
       
   642                 break;
       
   643                 }
       
   644 
       
   645             //-- failed to mount the file system, most likey it is not recognised
       
   646             pMountCB->Close(); //-- this is a self-destructing object!
       
   647             pMountCB = NULL;
       
   648             __PRINT(_L("#<<-@@ Mount FAILED !"));
       
   649             }
       
   650         else
       
   651             {
       
   652             //-- mounted OK, the file system is recognised
       
   653             __PRINT(_L("#<<-@@ Mount OK!"));
       
   654             
       
   655             pMatchedFS = pFS;
       
   656             break;
       
   657             }
       
   658     
       
   659         }//for(cntFS=0; cntFS<KNumFS; ++cntFS)
       
   660 
       
   661     if(cntFS >= KNumFS)
       
   662         {//-- no one from the FS factories recognised the file system
       
   663         __PRINT1(_L("#<<- ::TryMountFilesystem()[0x%x] No file system recognised!"), this);
       
   664         
       
   665         SetName(&KFileSystemName_AutoMounter); 
       
   666         return KErrCorrupt;
       
   667         }
       
   668 
       
   669     ASSERT(pMountCB && pMatchedFS); 
       
   670     *apMount = pMountCB;
       
   671     *apFS    = pMatchedFS;
       
   672     
       
   673     //-- set this FS name to the name of recognised FS. In this case the automounter "pretends" to be one of the child file systems on 
       
   674     //-- successful mounting. This behaviour was considered to be incorrect.
       
   675     //TPtrC fsName = pMatchedFS->Name();
       
   676     //SetName(&fsName); 
       
   677 
       
   678     return KErrNone;
       
   679 
       
   680     }
       
   681 
       
   682 //-----------------------------------------------------------------------------
       
   683 /**
       
   684     get the child file system object by the index in file child system names container
       
   685     
       
   686     @param  aIndex  index in the iFSNames
       
   687     @return pointer to the FS object if it is found, NULL otherwise
       
   688 */
       
   689 CFileSystem* CAutoMounterFileSystem::GetChildFileSystem(TUint aIndex) const
       
   690     {
       
   691     ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aIndex < iFSNames.Count());
       
   692 
       
   693     const TDesC& fsName = iFSNames[aIndex]; //-- registered child file system name
       
   694     CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container
       
   695 
       
   696     if(!pFS)
       
   697         {
       
   698         __PRINT1(_L("#<<- CAutoMounterFileSystem::GetChildFileSystem() FileServer doesn't have FS:%S Added!"), &fsName);
       
   699         Fault(EFileSysNotAdded);
       
   700         }
       
   701 
       
   702     return pFS;
       
   703     }
       
   704 
       
   705 //-----------------------------------------------------------------------------
       
   706 /**
       
   707     Find the child file system object by the file system name name hash. 
       
   708     @param  aFsNameHash FS name hash
       
   709     @return pointer to the FS object if it is found, NULL otherwise
       
   710 */
       
   711 CFileSystem* CAutoMounterFileSystem::GetChildFileSysteByNameHash(TUint32 aFsNameHash) const
       
   712     {
       
   713     ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aFsNameHash);
       
   714     
       
   715     for(TUint i=0; i<iFSNames.Count(); ++i)
       
   716         {
       
   717         if(aFsNameHash == iFSNames.GetStringHash(i))
       
   718             {
       
   719             const TDesC& fsName = iFSNames[i];        //-- registered child file system name
       
   720             __PRINT2(_L("#<<- ::GetChildFileSysteByNameHash() found FsName:%S by hash:0x%x"), &fsName, aFsNameHash);
       
   721             CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container
       
   722             ASSERT(pFS);
       
   723             return pFS;
       
   724             }
       
   725    
       
   726         }
       
   727    
       
   728     __PRINT1(_L("#<<- ::GetChildFileSysteByNameHash() No FS name found by hash:0x%x"), aFsNameHash);
       
   729    
       
   730     return NULL;
       
   731     }
       
   732 
       
   733 
       
   734 
       
   735 
       
   736 //#######################################################################################################################################
       
   737 //#     XStringArray implementation
       
   738 //#######################################################################################################################################
       
   739 
       
   740 XStringArray::XStringArray()
       
   741     {
       
   742     }
       
   743 
       
   744 XStringArray::~XStringArray()
       
   745     {
       
   746     Reset();
       
   747     iStrings.Close();
       
   748     }
       
   749 
       
   750 //-----------------------------------------------------------------------------
       
   751 void XStringArray::Reset()
       
   752     {
       
   753     iStrings.ResetAndDestroy();
       
   754     }
       
   755 
       
   756 //-----------------------------------------------------------------------------
       
   757 const TDesC& XStringArray::operator[](TUint aIndex) const
       
   758     {
       
   759     if(aIndex >= (TUint)iStrings.Count())
       
   760         Panic(EIndexOutOfRange);
       
   761 
       
   762     HBufC* des=iStrings[aIndex];
       
   763     return *des;
       
   764     }
       
   765 
       
   766 //-----------------------------------------------------------------------------
       
   767 /**
       
   768     Append file system name to the container. The name is converted to upper case.
       
   769     @param aString name descriptor.
       
   770     @return standard error code
       
   771 */
       
   772 TInt XStringArray::Append(const TDesC& aString)
       
   773     {
       
   774     HBufC* pBuf = aString.Alloc();
       
   775     if(!pBuf) 
       
   776         return KErrNoMemory;
       
   777     
       
   778     //-- string being appended shall be unique
       
   779     for(TUint i=0; i<Count(); ++i)
       
   780         {
       
   781         if(operator[](i).CompareF(aString) == 0)
       
   782             {
       
   783             ASSERT(0);
       
   784             return KErrNone;
       
   785             }
       
   786         }
       
   787 
       
   788     pBuf->Des().UpperCase(); //-- convert the FS name to upper-case in order to correctly calculate hash later
       
   789     return iStrings.Append(pBuf);
       
   790     }
       
   791 
       
   792 
       
   793 //-----------------------------------------------------------------------------
       
   794 /**
       
   795     Get child FS name hash by index in the names container.
       
   796     @param  aIndex name index in the container
       
   797     @return file system name hash (crc32)
       
   798 */
       
   799 TUint32 XStringArray::GetStringHash(TUint aIndex) const
       
   800     {
       
   801     const TDesC& des = operator[](aIndex);
       
   802     return TVolFormatParam::CalcFSNameHash(des);
       
   803     }
       
   804 
       
   805 
       
   806 
       
   807 void XStringArray::Panic(TPanicCode aPanicCode) const
       
   808     {
       
   809     _LIT(KPanicCat,"XStringArray");
       
   810     User::Panic(KPanicCat, aPanicCode);
       
   811     }
       
   812 
       
   813 
       
   814 
       
   815 
       
   816 
       
   817 
       
   818 
       
   819 
       
   820 
       
   821 
       
   822 
       
   823 
       
   824 
       
   825 
       
   826 
       
   827 
       
   828 
       
   829 
       
   830 
       
   831 
       
   832 
       
   833 
       
   834 
       
   835 
       
   836 
       
   837 
       
   838 
       
   839 
       
   840 
       
   841 
       
   842 
       
   843