| 0 |      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 | 
 |