Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
27 #include "filesystem_automounter.h"
28 #include "automounter.h"
31 //-----------------------------------------------------------------------------
33 void Fault(TFault aFault)
35 _LIT(KPanicName, "AutoMounter_fsy");
36 User::Panic(KPanicName, aFault);
40 //-----------------------------------------------------------------------------
43 Factory function, Create a new object of this file system
47 EXPORT_C CFileSystem* CreateFileSystem()
49 return CAutoMounterFileSystem::New();
54 //#######################################################################################################################################
55 //# CAutoMounterFileSystem class implementation
56 //#######################################################################################################################################
61 CAutoMounterFileSystem* CAutoMounterFileSystem::New()
63 CAutoMounterFileSystem* pThis = new CAutoMounterFileSystem();
68 CAutoMounterFileSystem::CAutoMounterFileSystem()
70 __PRINT1(_L("#<<- CAutoMounterFileSystem::CAutoMounterFileSystem() [0x%x]"), this);
75 CAutoMounterFileSystem::~CAutoMounterFileSystem()
77 __PRINT1(_L("#<<- CAutoMounterFileSystem::~CAutoMounterFileSystem() [0x%x]"), this);
80 //-----------------------------------------------------------------------------
83 Install iand initialise file system.
85 TInt CAutoMounterFileSystem::Install()
88 SetState(ENotInitialised);
90 __PRINT1(_L("#<<- CAutoMounterFileSystem::Install() [0x%x]"), this);
92 iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber);
94 InitialiseFileSystem();
96 return SetName(&KFileSystemName_AutoMounter);
100 //-----------------------------------------------------------------------------
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
107 CMountCB* CAutoMounterFileSystem::NewMountL() const
109 __PRINT1(_L("#<<- CAutoMounterFileSystem::NewMountL() [0x%x]"), this);
110 ASSERT(State() == EInitialised);
112 __PRINT1(_L("#<<- producing the _default_ filesystem:%S"), &iFSNames[KDefaultFSNo]);
114 CFileSystem* pFS = GetChildFileSystem(KDefaultFSNo);
117 return pFS->NewMountL();
120 //-----------------------------------------------------------------------------
124 CFileCB* CAutoMounterFileSystem::NewFileL() const
126 __PRINT1(_L("#<<- CAutoMounterFileSystem::NewFileL() [0x%x]"), this);
127 Fault(EMustNotBeCalled);
131 //-----------------------------------------------------------------------------
133 Create a new directory object
135 CDirCB* CAutoMounterFileSystem::NewDirL() const
137 __PRINT1(_L("#<<- CAutoMounterFileSystem::NewDirL() [0x%x]"), this);
138 Fault(EMustNotBeCalled);
142 //-----------------------------------------------------------------------------
144 Create a new media formatter
146 CFormatCB* CAutoMounterFileSystem::NewFormatL() const
148 __PRINT1(_L("#<<- CAutoMounterFileSystem::NewFormatL() [0x%x]"), this);
149 Fault(EMustNotBeCalled);
154 //-----------------------------------------------------------------------------
158 Called by File Server before deleting File System object.
160 TInt CAutoMounterFileSystem::Remove()
162 __PRINT1(_L("#<<- CAutoMounterFileSystem::Remove() [0x%x]"), this);
163 return CFileSystem::Remove();
166 //-----------------------------------------------------------------------------
170 TBool CAutoMounterFileSystem::QueryVersionSupported(const TVersion& aVer) const
172 __PRINT1(_L("#<<- CAutoMounterFileSystem::QueryVersionSupported() [0x%x]"), this);
173 return CFileSystem::QueryVersionSupported(aVer);
178 //-----------------------------------------------------------------------------
181 Find out if drive extensions are supported. In order to have consistent behaviour, _all_ child
182 file systems shall behave the same way.
184 @return ETrue if drive extensions are supported.
186 TBool CAutoMounterFileSystem::IsExtensionSupported() const
188 __PRINT1(_L("#<<- CAutoMounterFileSystem::IsExtensionSupported() [0x%x]"), this);
190 ASSERT(State() == EInitialised && iFSNames.Count() > 1);
193 //-- in debug mode check file systems compatibility: ALL childs must support this feature
194 for(TUint i=0; i<iFSNames.Count(); ++i)
196 if( !(GetChildFileSystem(i)->IsExtensionSupported()))
198 DBG_STATEMENT(Fault(EIncompatibleFileSystems));
199 __PRINT(_L("#<<- ::IsExtensionSupported(): Incompatible file sytems!"));
208 //-----------------------------------------------------------------------------
211 Return the initial default path.
213 TInt CAutoMounterFileSystem::DefaultPath(TDes& aPath) const
215 __PRINT1(_L("#<<- CAutoMounterFileSystem::DefaultPath() [0x%x]"), this);
218 aPath[0] = (TUint8) RFs::GetSystemDriveChar();
223 //-----------------------------------------------------------------------------
226 Additional interfaces support.
228 TInt CAutoMounterFileSystem::GetInterface(TInt aInterfaceId, TAny*& aInterface, TAny* aInput)
231 __PRINT2(_L("#<<- CAutoMounterFileSystem::GetInterface(id:%d) [0x%x]"), aInterfaceId, this);
235 //-- It is this filesystem private interface.
236 case EExtendedFunctionality:
237 aInterface = (CFileSystem::MFileSystemExtInterface*)this;
240 //-- a special case for child filesystems.
241 //-- ALL of them must respond to this interface query exactly the same way. I.e. It is impossible
242 //-- to have some of the child FS supporting it and some not.
243 case EProxyDriveSupport:
244 return DoProcessProxyDriveSupport();
248 //-- This is the request to other (child file system) from the file server
249 //-- Actually, this part must never be called. File Server shall query the file system interfaces _after_ mounting the concrete FS
250 //-- calling TDrive::iCurrentMount->FileSystem().GetInterface()
252 return CFileSystem::GetInterface(aInterfaceId, aInterface, aInput);
258 //-----------------------------------------------------------------------------
261 Find out if _all_ child file systems support the proxy drive. All childs shall behave exactly the same way.
262 @return KErrNone if all child file systems support proxy drives, or KErrNotSupported if all of them do not.
264 TInt CAutoMounterFileSystem::DoProcessProxyDriveSupport()
266 __PRINT1(_L("#<<- CAutoMounterFileSystem::DoProcessProxyDriveSupport[0x%x]"), this);
267 ASSERT(State() == EInitialised);
269 const TUint cnt = iFSNames.Count();
273 //-- query the default filesystem #0
274 const TBool bRes = GetChildFileSystem(KDefaultFSNo)->IsProxyDriveSupported();
276 //-- query the rest of child filesystems
277 for(TUint i=1; i<cnt; ++i)
279 const TBool b = GetChildFileSystem(i)->IsProxyDriveSupported();
282 Fault(EIncompatibleFileSystems);
286 return bRes ? KErrNone : KErrNotSupported;
289 //-----------------------------------------------------------------------------
291 Get the child file system name by its index (enumerator).
293 @param aFsNumber index of the child FS 0...KMaxTInt
294 @param aFsName on success the child file system name will be placed into this buffer
296 @return KErrNone if there is a child FS name with index 'aFsNumber' (child FS 'aFsNumber' is supported by automounter)
297 KErrNotFound if child FS 'aFsNumber' is not supported
299 TInt CAutoMounterFileSystem::GetSupportedFileSystemName(TInt aFsNumber, TDes& aFsName) const
301 __PRINT2(_L("#<<- CAutoMounterFileSystem::GetSupportedFileSystemName[0x%x](%d)"), this, aFsNumber);
303 if(aFsNumber == RFs::KRootFileSystem)
304 {//-- this is a name query for "root filesystem" or automounter
305 aFsName = Name(); //-- ourselves
309 //-- this is a query for one of the child filesystems
310 if((TUint)aFsNumber < iFSNames.Count())
312 aFsName = iFSNames[aFsNumber];
321 //-----------------------------------------------------------------------------
323 This is the only factory method that can be called by file server for this file system.
324 In this method the automounter sequentially tries to mount every child and on success produces the corresponding CMountCB object.
326 @param apDrive pointer to the TDrive, child FS will need this to access media.
327 @param apFileSystem on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if
328 one of the child file system has recognised the volume.
329 @param aForceMount if ETrue the appropriate child FS (designated by aFsNameHash) will be forcedly mounted on the volume. for volume formatting purposes.
330 @param aFsNameHash if !=0 specifies the file system name, see TVolFormatParam::CalcFSNameHash(). 0 means "file system name is not specified"
332 @return pointer to the constructed CMountCB by one of the child file systems (and pointer to this child FS in apFileSystem)
333 NULL if it was impossible to produce proper CMountCB object.
336 CMountCB* CAutoMounterFileSystem::NewMountExL(TDrive* apDrive, CFileSystem** apFileSystem, TBool aForceMount, TUint32 aFsNameHash)
338 __PRINT4(_L("#<<- CAutoMounterFileSystem::NewMountExL[0x%x] drv:%d, ForceMount:%d, FSNameHash:0x%x"), this, apDrive->DriveNumber(), aForceMount, aFsNameHash);
340 ASSERT(State() == EInitialised && apDrive);
342 //-- This method is usually called from the appropriate drive thread; this file system is intended to be bound to
343 //-- removable drives. Having removable drive runnind in the main file server thread means that something is terribly wrongly configured.
344 if(apDrive->IsSynchronous())
345 Fault(EWrongDriveAttributes);
347 if(iFSNames.Count() < 2)
348 Fault(EWrongConfiguration);
351 //-- if aForceMount is true, this means that the TDrive tries mount the filesystem by force for formatting because normal mounting has failed before.
352 //-- in our case it means that the file system on the volume hadn't been recognised by any child FS.
353 //-- aFsNameHash shall designate the file system to be forcedly mounted. Depending on this the appropriat CMounCB object will be produced.
354 //-- if aFsNameHash is 0, i.e. not provided, this method will fail with KErrNotFound because it is impossible to select appropriat child FS.
358 {//-- the file system to mount forcedly is not specified
359 __PRINT(_L("#<<- Unable to select appropriate child FS for formatting!"));
360 User::Leave(KErrNotFound);
363 {//-- try to find appropriate child FS by its name hash
364 CFileSystem *pFS = GetChildFileSysteByNameHash(aFsNameHash);
367 __PRINT(_L("#<<- no child FS found by its name hash!"));
369 User::Leave(KErrNotFound);
372 CMountCB* pMount = pFS->NewMountL();
382 //-- try instantiate a new CMountCB depending on the file system on the media
384 CMountCB* pMatchedMount;
385 TInt nRes = TryMountFilesystem(apDrive, &pMatchedMount, apFileSystem);
389 ASSERT(pMatchedMount);
390 return pMatchedMount;
399 //-----------------------------------------------------------------------------
401 Initialise this file system. Reads and processes configuration, fills in file system names container, etc.
403 void CAutoMounterFileSystem::InitialiseFileSystem()
405 __PRINT1(_L("#<<- CAutoMounterFileSystem::InitialiseFileSystem() [0x%x]"), this);
407 ASSERT(State() == ENotInitialised);
412 //-- 1. initialise the array of file system names. These names shall be listed in a config string.
413 //-- the config string is taken from estart.txt usually and its format is like this:
414 //-- section: [AutoMounter] and property "FSNames fat,exfat"
415 //-- in debug version a special text property can override the config string. This allows controlling automounter from
416 //-- the test environment.
423 const TUid KSID_Test1={0x10210EB3}; //-- SID of the test that will define and set test property to control volume mounting
424 const TUint KPropKey = 0; //-- property key
426 //-- in debug mode the property will override the estart.txt config
427 if(RProperty::Get(KSID_Test1, KPropKey, buf) == KErrNone)
429 __PRINT(_L("#<<- reading config from the debug propery..."));
434 __PRINT(_L("#<<- reading config from estart.txt..."));
435 _LIT8(KSection, "AutoMounter");
436 _LIT8(KProperty, "FSNames");
438 nRes = F32Properties::GetString(KSection, KProperty, buf);
440 Fault(EPluginInitialise);
445 __PRINT1(_L("#<<- config:'%S'"), &fsName);
447 //-- parse CSV config line and fill in the file system names array
448 const TChar chDelim = ','; //-- token delimiter, comma
450 TPtrC8 ptrCurrLine(buf);
453 const TInt delimPos = ptrCurrLine.Locate(chDelim);
456 fsName.Copy(ptrCurrLine);
460 TPtrC8 temp(ptrCurrLine.Ptr(), delimPos);
465 __PRINT2(_L("#<<- child FS[%d]: '%S'"), i, &fsName);
468 if(fsName.Length() <= 0)
469 Fault(EPluginInitialise);
471 //-- check if the FS name being appended is unique
472 for(TUint j=0; j<iFSNames.Count(); ++j)
474 if(iFSNames[j] == fsName)
476 Fault(EPluginInitialise);
481 nRes = iFSNames.Append(fsName);
482 ASSERT(nRes ==KErrNone);
487 ptrCurrLine.Set(ptrCurrLine.Ptr()+delimPos+1, ptrCurrLine.Length()-delimPos-1);
491 SetState(EInitialised);
493 //-- 2. check that the file server has all filesystems we need instantiated and stored in a global container
494 TUint cnt = iFSNames.Count();
497 __PRINT(_L("#<<- ::InitialiseFileSystem(): too few File Systems bound!"));
498 Fault(EPluginInitialise);
503 GetChildFileSystem(cnt);
511 //-----------------------------------------------------------------------------
513 Tries to find out if some of the child file systems can be mounted on the given volume.
515 @param apDrive pointer to the TDrive, child FS will need this to access media.
516 @param on return will contain the pointer to the CMountCB object if some of the childs has decided that it can be mounted.
517 @param apFS on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if
519 @return KErrNone on success, otherwise standard error code.
522 TInt CAutoMounterFileSystem::TryMountFilesystem(TDrive* apDrive, CMountCB** apMount, CFileSystem** apFS)
524 __PRINT1(_L("#<<- CAutoMounterFileSystem::TryMountFilesystem()[0x%x]"), this);
526 const TInt KNumFS = iFSNames.Count();
528 ASSERT(State() == EInitialised && (KNumFS >1));
537 CMountCB* pMountCB = NULL;
538 CFileSystem* pMatchedFS = NULL;
540 for(cntFS=0; cntFS < KNumFS; ++cntFS)
543 __PRINT2(_L("#<<-@@ trying FS[%d]:%S"), cntFS, &iFSNames[cntFS]);
545 CFileSystem* pFS = GetChildFileSystem(cntFS); //-- Find current filesystem object in the FileServer's global container
547 //-- 2. create CMountCB instance and set it up
550 TRAP(nRes, pMountCB = pFS->NewMountL());
557 pMountCB->SetDrive(apDrive);
560 //-- 2.1 Firstly try using special CMountCB interface to find out if current FS can be mounted on this media
561 nRes = pMountCB->CheckFileSystemMountable();
562 if(nRes == KErrNotSupported)
564 //-- file system doesn't support this feature,
565 //-- 2.2 try to check the file system by mounting and dismounting later. It can result in some long activity, like FAT scanning etc.
566 TRAP(nRes, pMountCB->MountL(EFalse));
567 pMountCB->Dismounted(); //-- dismount the mountCB, it will be required in dismounted state anyway
570 //-- 2.3 analyse the result of mounting
573 if(nRes == KErrLocked)
574 {//-- this is a special case; The media (SD card for example) is locked.
575 //-- Pretend that everything is OK and return CMountCB instance that is produced by the _default_ file system.
576 //-- locked media case will be handled by the file server later.
577 ASSERT(cntFS == KDefaultFSNo); //-- the default FS is tried first and must detect the locked media
579 __PRINT(_L("#<<-@@ The media is LOCKED !"));
583 //-- failed to mount the file system, most likey it is not recognised
584 pMountCB->Close(); //-- this is a self-destructing object!
586 __PRINT(_L("#<<-@@ Mount FAILED !"));
590 //-- mounted OK, the file system is recognised
591 __PRINT(_L("#<<-@@ Mount OK!"));
597 }//for(cntFS=0; cntFS<KNumFS; ++cntFS)
600 {//-- no one from the FS factories recognised the file system
601 __PRINT1(_L("#<<- ::TryMountFilesystem()[0x%x] No file system recognised!"), this);
603 SetName(&KFileSystemName_AutoMounter);
607 ASSERT(pMountCB && pMatchedFS);
611 //-- 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
612 //-- successful mounting. This behaviour was considered to be incorrect.
613 //TPtrC fsName = pMatchedFS->Name();
620 //-----------------------------------------------------------------------------
622 get the child file system object by the index in file child system names container
624 @param aIndex index in the iFSNames
625 @return pointer to the FS object if it is found, NULL otherwise
627 CFileSystem* CAutoMounterFileSystem::GetChildFileSystem(TUint aIndex) const
629 ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aIndex < iFSNames.Count());
631 const TDesC& fsName = iFSNames[aIndex]; //-- registered child file system name
632 CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container
636 __PRINT1(_L("#<<- CAutoMounterFileSystem::GetChildFileSystem() FileServer doesn't have FS:%S Added!"), &fsName);
637 Fault(EFileSysNotAdded);
643 //-----------------------------------------------------------------------------
645 Find the child file system object by the file system name name hash.
646 @param aFsNameHash FS name hash
647 @return pointer to the FS object if it is found, NULL otherwise
649 CFileSystem* CAutoMounterFileSystem::GetChildFileSysteByNameHash(TUint32 aFsNameHash) const
651 ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aFsNameHash);
653 for(TUint i=0; i<iFSNames.Count(); ++i)
655 if(aFsNameHash == iFSNames.GetStringHash(i))
657 const TDesC& fsName = iFSNames[i]; //-- registered child file system name
658 __PRINT2(_L("#<<- ::GetChildFileSysteByNameHash() found FsName:%S by hash:0x%x"), &fsName, aFsNameHash);
659 CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container
666 __PRINT1(_L("#<<- ::GetChildFileSysteByNameHash() No FS name found by hash:0x%x"), aFsNameHash);
674 //#######################################################################################################################################
675 //# XStringArray implementation
676 //#######################################################################################################################################
678 XStringArray::XStringArray()
682 XStringArray::~XStringArray()
688 //-----------------------------------------------------------------------------
689 void XStringArray::Reset()
691 iStrings.ResetAndDestroy();
694 //-----------------------------------------------------------------------------
695 const TDesC& XStringArray::operator[](TUint aIndex) const
697 if(aIndex >= (TUint)iStrings.Count())
698 Panic(EIndexOutOfRange);
700 HBufC* des=iStrings[aIndex];
704 //-----------------------------------------------------------------------------
706 Append file system name to the container. The name is converted to upper case.
707 @param aString name descriptor.
708 @return standard error code
710 TInt XStringArray::Append(const TDesC& aString)
712 HBufC* pBuf = aString.Alloc();
716 //-- string being appended shall be unique
717 for(TUint i=0; i<Count(); ++i)
719 if(operator[](i).CompareF(aString) == 0)
726 pBuf->Des().UpperCase(); //-- convert the FS name to upper-case in order to correctly calculate hash later
727 return iStrings.Append(pBuf);
731 //-----------------------------------------------------------------------------
733 Get child FS name hash by index in the names container.
734 @param aIndex name index in the container
735 @return file system name hash (crc32)
737 TUint32 XStringArray::GetStringHash(TUint aIndex) const
739 const TDesC& des = operator[](aIndex);
740 return TVolFormatParam::CalcFSNameHash(des);
745 void XStringArray::Panic(TPanicCode aPanicCode) const
747 _LIT(KPanicCat,"XStringArray");
748 User::Panic(KPanicCat, aPanicCode);