sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: sl@0: #include "filesystem_automounter.h" sl@0: #include "automounter.h" sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: void Fault(TFault aFault) sl@0: { sl@0: _LIT(KPanicName, "AutoMounter_fsy"); sl@0: User::Panic(KPanicName, aFault); sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Factory function, Create a new object of this file system sl@0: */ sl@0: extern "C" sl@0: { sl@0: EXPORT_C CFileSystem* CreateFileSystem() sl@0: { sl@0: return CAutoMounterFileSystem::New(); sl@0: } sl@0: } sl@0: sl@0: sl@0: //####################################################################################################################################### sl@0: //# CAutoMounterFileSystem class implementation sl@0: //####################################################################################################################################### sl@0: sl@0: /** sl@0: Factory method sl@0: */ sl@0: CAutoMounterFileSystem* CAutoMounterFileSystem::New() sl@0: { sl@0: CAutoMounterFileSystem* pThis = new CAutoMounterFileSystem(); sl@0: return pThis; sl@0: } sl@0: sl@0: sl@0: CAutoMounterFileSystem::CAutoMounterFileSystem() sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::CAutoMounterFileSystem() [0x%x]"), this); sl@0: sl@0: SetState(EInvalid); sl@0: } sl@0: sl@0: CAutoMounterFileSystem::~CAutoMounterFileSystem() sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::~CAutoMounterFileSystem() [0x%x]"), this); sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Install iand initialise file system. sl@0: */ sl@0: TInt CAutoMounterFileSystem::Install() sl@0: { sl@0: sl@0: SetState(ENotInitialised); sl@0: sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::Install() [0x%x]"), this); sl@0: sl@0: iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber); sl@0: sl@0: InitialiseFileSystem(); sl@0: sl@0: return SetName(&KFileSystemName_AutoMounter); sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Create a new mount control block. sl@0: 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 sl@0: corresponding media driver. E.g. TDrive::ForceRemountDrive() sl@0: Produce the _default_ file system mount sl@0: */ sl@0: CMountCB* CAutoMounterFileSystem::NewMountL() const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::NewMountL() [0x%x]"), this); sl@0: ASSERT(State() == EInitialised); sl@0: sl@0: __PRINT1(_L("#<<- producing the _default_ filesystem:%S"), &iFSNames[KDefaultFSNo]); sl@0: sl@0: CFileSystem* pFS = GetChildFileSystem(KDefaultFSNo); sl@0: ASSERT(pFS); sl@0: sl@0: return pFS->NewMountL(); sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Create a new file. sl@0: */ sl@0: CFileCB* CAutoMounterFileSystem::NewFileL() const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::NewFileL() [0x%x]"), this); sl@0: Fault(EMustNotBeCalled); sl@0: return NULL; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Create a new directory object sl@0: */ sl@0: CDirCB* CAutoMounterFileSystem::NewDirL() const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::NewDirL() [0x%x]"), this); sl@0: Fault(EMustNotBeCalled); sl@0: return NULL; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Create a new media formatter sl@0: */ sl@0: CFormatCB* CAutoMounterFileSystem::NewFormatL() const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::NewFormatL() [0x%x]"), this); sl@0: Fault(EMustNotBeCalled); sl@0: return NULL; sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: #ifdef _DEBUG sl@0: /** sl@0: Called by File Server before deleting File System object. sl@0: */ sl@0: TInt CAutoMounterFileSystem::Remove() sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::Remove() [0x%x]"), this); sl@0: return CFileSystem::Remove(); sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: */ sl@0: TBool CAutoMounterFileSystem::QueryVersionSupported(const TVersion& aVer) const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::QueryVersionSupported() [0x%x]"), this); sl@0: return CFileSystem::QueryVersionSupported(aVer); sl@0: } sl@0: sl@0: #endif sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Find out if drive extensions are supported. In order to have consistent behaviour, _all_ child sl@0: file systems shall behave the same way. sl@0: sl@0: @return ETrue if drive extensions are supported. sl@0: */ sl@0: TBool CAutoMounterFileSystem::IsExtensionSupported() const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::IsExtensionSupported() [0x%x]"), this); sl@0: sl@0: ASSERT(State() == EInitialised && iFSNames.Count() > 1); sl@0: sl@0: sl@0: //-- in debug mode check file systems compatibility: ALL childs must support this feature sl@0: for(TUint i=0; iIsExtensionSupported())) sl@0: { sl@0: DBG_STATEMENT(Fault(EIncompatibleFileSystems)); sl@0: __PRINT(_L("#<<- ::IsExtensionSupported(): Incompatible file sytems!")); sl@0: return EFalse; sl@0: } sl@0: } sl@0: sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Return the initial default path. sl@0: */ sl@0: TInt CAutoMounterFileSystem::DefaultPath(TDes& aPath) const sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::DefaultPath() [0x%x]"), this); sl@0: sl@0: aPath=_L("?:\\"); sl@0: aPath[0] = (TUint8) RFs::GetSystemDriveChar(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Additional interfaces support. sl@0: */ sl@0: TInt CAutoMounterFileSystem::GetInterface(TInt aInterfaceId, TAny*& aInterface, TAny* aInput) sl@0: { sl@0: sl@0: __PRINT2(_L("#<<- CAutoMounterFileSystem::GetInterface(id:%d) [0x%x]"), aInterfaceId, this); sl@0: sl@0: switch(aInterfaceId) sl@0: { sl@0: //-- It is this filesystem private interface. sl@0: case EExtendedFunctionality: sl@0: aInterface = (CFileSystem::MFileSystemExtInterface*)this; sl@0: return KErrNone; sl@0: sl@0: //-- a special case for child filesystems. sl@0: //-- ALL of them must respond to this interface query exactly the same way. I.e. It is impossible sl@0: //-- to have some of the child FS supporting it and some not. sl@0: case EProxyDriveSupport: sl@0: return DoProcessProxyDriveSupport(); sl@0: sl@0: sl@0: default: sl@0: //-- This is the request to other (child file system) from the file server sl@0: //-- Actually, this part must never be called. File Server shall query the file system interfaces _after_ mounting the concrete FS sl@0: //-- calling TDrive::iCurrentMount->FileSystem().GetInterface() sl@0: ASSERT(0); sl@0: return CFileSystem::GetInterface(aInterfaceId, aInterface, aInput); sl@0: sl@0: } sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Find out if _all_ child file systems support the proxy drive. All childs shall behave exactly the same way. sl@0: @return KErrNone if all child file systems support proxy drives, or KErrNotSupported if all of them do not. sl@0: */ sl@0: TInt CAutoMounterFileSystem::DoProcessProxyDriveSupport() sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::DoProcessProxyDriveSupport[0x%x]"), this); sl@0: ASSERT(State() == EInitialised); sl@0: sl@0: const TUint cnt = iFSNames.Count(); sl@0: ASSERT(cnt > 1); sl@0: sl@0: sl@0: //-- query the default filesystem #0 sl@0: const TBool bRes = GetChildFileSystem(KDefaultFSNo)->IsProxyDriveSupported(); sl@0: sl@0: //-- query the rest of child filesystems sl@0: for(TUint i=1; iIsProxyDriveSupported(); sl@0: sl@0: if(BoolXOR(b, bRes)) sl@0: Fault(EIncompatibleFileSystems); sl@0: } sl@0: sl@0: sl@0: return bRes ? KErrNone : KErrNotSupported; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Get the child file system name by its index (enumerator). sl@0: sl@0: @param aFsNumber index of the child FS 0...KMaxTInt sl@0: @param aFsName on success the child file system name will be placed into this buffer sl@0: sl@0: @return KErrNone if there is a child FS name with index 'aFsNumber' (child FS 'aFsNumber' is supported by automounter) sl@0: KErrNotFound if child FS 'aFsNumber' is not supported sl@0: */ sl@0: TInt CAutoMounterFileSystem::GetSupportedFileSystemName(TInt aFsNumber, TDes& aFsName) const sl@0: { sl@0: __PRINT2(_L("#<<- CAutoMounterFileSystem::GetSupportedFileSystemName[0x%x](%d)"), this, aFsNumber); sl@0: sl@0: if(aFsNumber == RFs::KRootFileSystem) sl@0: {//-- this is a name query for "root filesystem" or automounter sl@0: aFsName = Name(); //-- ourselves sl@0: return KErrNone; sl@0: } sl@0: sl@0: //-- this is a query for one of the child filesystems sl@0: if((TUint)aFsNumber < iFSNames.Count()) sl@0: { sl@0: aFsName = iFSNames[aFsNumber]; sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: This is the only factory method that can be called by file server for this file system. sl@0: In this method the automounter sequentially tries to mount every child and on success produces the corresponding CMountCB object. sl@0: sl@0: @param apDrive pointer to the TDrive, child FS will need this to access media. sl@0: @param apFileSystem on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if sl@0: one of the child file system has recognised the volume. sl@0: @param aForceMount if ETrue the appropriate child FS (designated by aFsNameHash) will be forcedly mounted on the volume. for volume formatting purposes. sl@0: @param aFsNameHash if !=0 specifies the file system name, see TVolFormatParam::CalcFSNameHash(). 0 means "file system name is not specified" sl@0: sl@0: @return pointer to the constructed CMountCB by one of the child file systems (and pointer to this child FS in apFileSystem) sl@0: NULL if it was impossible to produce proper CMountCB object. sl@0: sl@0: */ sl@0: CMountCB* CAutoMounterFileSystem::NewMountExL(TDrive* apDrive, CFileSystem** apFileSystem, TBool aForceMount, TUint32 aFsNameHash) sl@0: { sl@0: __PRINT4(_L("#<<- CAutoMounterFileSystem::NewMountExL[0x%x] drv:%d, ForceMount:%d, FSNameHash:0x%x"), this, apDrive->DriveNumber(), aForceMount, aFsNameHash); sl@0: sl@0: ASSERT(State() == EInitialised && apDrive); sl@0: sl@0: //-- This method is usually called from the appropriate drive thread; this file system is intended to be bound to sl@0: //-- removable drives. Having removable drive runnind in the main file server thread means that something is terribly wrongly configured. sl@0: if(apDrive->IsSynchronous()) sl@0: Fault(EWrongDriveAttributes); sl@0: sl@0: if(iFSNames.Count() < 2) sl@0: Fault(EWrongConfiguration); sl@0: sl@0: sl@0: //-- if aForceMount is true, this means that the TDrive tries mount the filesystem by force for formatting because normal mounting has failed before. sl@0: //-- in our case it means that the file system on the volume hadn't been recognised by any child FS. sl@0: //-- aFsNameHash shall designate the file system to be forcedly mounted. Depending on this the appropriat CMounCB object will be produced. sl@0: //-- if aFsNameHash is 0, i.e. not provided, this method will fail with KErrNotFound because it is impossible to select appropriat child FS. sl@0: if(aForceMount) sl@0: { sl@0: if(aFsNameHash == 0) sl@0: {//-- the file system to mount forcedly is not specified sl@0: __PRINT(_L("#<<- Unable to select appropriate child FS for formatting!")); sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: else sl@0: {//-- try to find appropriate child FS by its name hash sl@0: CFileSystem *pFS = GetChildFileSysteByNameHash(aFsNameHash); sl@0: if(!pFS) sl@0: { sl@0: __PRINT(_L("#<<- no child FS found by its name hash!")); sl@0: ASSERT(0); sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: sl@0: CMountCB* pMount = pFS->NewMountL(); sl@0: ASSERT(pMount); sl@0: sl@0: *apFileSystem = pFS; sl@0: return pMount; sl@0: } sl@0: }//if(aForceMount) sl@0: sl@0: sl@0: sl@0: //-- try instantiate a new CMountCB depending on the file system on the media sl@0: sl@0: CMountCB* pMatchedMount; sl@0: TInt nRes = TryMountFilesystem(apDrive, &pMatchedMount, apFileSystem); sl@0: sl@0: if(nRes == KErrNone) sl@0: { sl@0: ASSERT(pMatchedMount); sl@0: return pMatchedMount; sl@0: } sl@0: sl@0: sl@0: sl@0: User::Leave(nRes); sl@0: return NULL; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Initialise this file system. Reads and processes configuration, fills in file system names container, etc. sl@0: */ sl@0: void CAutoMounterFileSystem::InitialiseFileSystem() sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::InitialiseFileSystem() [0x%x]"), this); sl@0: sl@0: ASSERT(State() == ENotInitialised); sl@0: sl@0: TInt nRes; sl@0: sl@0: sl@0: //-- 1. initialise the array of file system names. These names shall be listed in a config string. sl@0: //-- the config string is taken from estart.txt usually and its format is like this: sl@0: //-- section: [AutoMounter] and property "FSNames fat,exfat" sl@0: //-- in debug version a special text property can override the config string. This allows controlling automounter from sl@0: //-- the test environment. sl@0: sl@0: TBuf8<0x100> buf(0); sl@0: TBuf<0x100> fsName; sl@0: sl@0: sl@0: #ifdef _DEBUG sl@0: const TUid KSID_Test1={0x10210EB3}; //-- SID of the test that will define and set test property to control volume mounting sl@0: const TUint KPropKey = 0; //-- property key sl@0: sl@0: //-- in debug mode the property will override the estart.txt config sl@0: if(RProperty::Get(KSID_Test1, KPropKey, buf) == KErrNone) sl@0: { sl@0: __PRINT(_L("#<<- reading config from the debug propery...")); sl@0: } sl@0: else sl@0: #endif sl@0: { sl@0: __PRINT(_L("#<<- reading config from estart.txt...")); sl@0: _LIT8(KSection, "AutoMounter"); sl@0: _LIT8(KProperty, "FSNames"); sl@0: sl@0: nRes = F32Properties::GetString(KSection, KProperty, buf); sl@0: if(!nRes) sl@0: Fault(EPluginInitialise); sl@0: } sl@0: sl@0: sl@0: fsName.Copy(buf); sl@0: __PRINT1(_L("#<<- config:'%S'"), &fsName); sl@0: sl@0: //-- parse CSV config line and fill in the file system names array sl@0: const TChar chDelim = ','; //-- token delimiter, comma sl@0: buf.Trim(); sl@0: TPtrC8 ptrCurrLine(buf); sl@0: for(TInt i=0; ;++i) sl@0: { sl@0: const TInt delimPos = ptrCurrLine.Locate(chDelim); sl@0: if(delimPos <= 0) sl@0: { sl@0: fsName.Copy(ptrCurrLine); sl@0: } sl@0: else sl@0: { sl@0: TPtrC8 temp(ptrCurrLine.Ptr(), delimPos); sl@0: fsName.Copy(temp); sl@0: } sl@0: sl@0: fsName.Trim(); sl@0: __PRINT2(_L("#<<- child FS[%d]: '%S'"), i, &fsName); sl@0: sl@0: sl@0: if(fsName.Length() <= 0) sl@0: Fault(EPluginInitialise); sl@0: sl@0: //-- check if the FS name being appended is unique sl@0: for(TUint j=0; j1)); sl@0: sl@0: sl@0: *apMount = NULL; sl@0: *apFS = NULL; sl@0: sl@0: sl@0: TInt nRes; sl@0: TInt cntFS; sl@0: CMountCB* pMountCB = NULL; sl@0: CFileSystem* pMatchedFS = NULL; sl@0: sl@0: for(cntFS=0; cntFS < KNumFS; ++cntFS) sl@0: { sl@0: sl@0: __PRINT2(_L("#<<-@@ trying FS[%d]:%S"), cntFS, &iFSNames[cntFS]); sl@0: sl@0: CFileSystem* pFS = GetChildFileSystem(cntFS); //-- Find current filesystem object in the FileServer's global container sl@0: sl@0: //-- 2. create CMountCB instance and set it up sl@0: pMountCB = NULL; sl@0: sl@0: TRAP(nRes, pMountCB = pFS->NewMountL()); sl@0: if(nRes != KErrNone) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: ASSERT(pMountCB); sl@0: pMountCB->SetDrive(apDrive); sl@0: sl@0: sl@0: //-- 2.1 Firstly try using special CMountCB interface to find out if current FS can be mounted on this media sl@0: nRes = pMountCB->CheckFileSystemMountable(); sl@0: if(nRes == KErrNotSupported) sl@0: { sl@0: //-- file system doesn't support this feature, sl@0: //-- 2.2 try to check the file system by mounting and dismounting later. It can result in some long activity, like FAT scanning etc. sl@0: TRAP(nRes, pMountCB->MountL(EFalse)); sl@0: pMountCB->Dismounted(); //-- dismount the mountCB, it will be required in dismounted state anyway sl@0: } sl@0: sl@0: //-- 2.3 analyse the result of mounting sl@0: if(nRes != KErrNone) sl@0: { sl@0: if(nRes == KErrLocked) sl@0: {//-- this is a special case; The media (SD card for example) is locked. sl@0: //-- Pretend that everything is OK and return CMountCB instance that is produced by the _default_ file system. sl@0: //-- locked media case will be handled by the file server later. sl@0: ASSERT(cntFS == KDefaultFSNo); //-- the default FS is tried first and must detect the locked media sl@0: pMatchedFS = pFS; sl@0: __PRINT(_L("#<<-@@ The media is LOCKED !")); sl@0: break; sl@0: } sl@0: sl@0: //-- failed to mount the file system, most likey it is not recognised sl@0: pMountCB->Close(); //-- this is a self-destructing object! sl@0: pMountCB = NULL; sl@0: __PRINT(_L("#<<-@@ Mount FAILED !")); sl@0: } sl@0: else sl@0: { sl@0: //-- mounted OK, the file system is recognised sl@0: __PRINT(_L("#<<-@@ Mount OK!")); sl@0: sl@0: pMatchedFS = pFS; sl@0: break; sl@0: } sl@0: sl@0: }//for(cntFS=0; cntFS= KNumFS) sl@0: {//-- no one from the FS factories recognised the file system sl@0: __PRINT1(_L("#<<- ::TryMountFilesystem()[0x%x] No file system recognised!"), this); sl@0: sl@0: SetName(&KFileSystemName_AutoMounter); sl@0: return KErrCorrupt; sl@0: } sl@0: sl@0: ASSERT(pMountCB && pMatchedFS); sl@0: *apMount = pMountCB; sl@0: *apFS = pMatchedFS; sl@0: sl@0: //-- 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 sl@0: //-- successful mounting. This behaviour was considered to be incorrect. sl@0: //TPtrC fsName = pMatchedFS->Name(); sl@0: //SetName(&fsName); sl@0: sl@0: return KErrNone; sl@0: sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: get the child file system object by the index in file child system names container sl@0: sl@0: @param aIndex index in the iFSNames sl@0: @return pointer to the FS object if it is found, NULL otherwise sl@0: */ sl@0: CFileSystem* CAutoMounterFileSystem::GetChildFileSystem(TUint aIndex) const sl@0: { sl@0: ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aIndex < iFSNames.Count()); sl@0: sl@0: const TDesC& fsName = iFSNames[aIndex]; //-- registered child file system name sl@0: CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container sl@0: sl@0: if(!pFS) sl@0: { sl@0: __PRINT1(_L("#<<- CAutoMounterFileSystem::GetChildFileSystem() FileServer doesn't have FS:%S Added!"), &fsName); sl@0: Fault(EFileSysNotAdded); sl@0: } sl@0: sl@0: return pFS; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Find the child file system object by the file system name name hash. sl@0: @param aFsNameHash FS name hash sl@0: @return pointer to the FS object if it is found, NULL otherwise sl@0: */ sl@0: CFileSystem* CAutoMounterFileSystem::GetChildFileSysteByNameHash(TUint32 aFsNameHash) const sl@0: { sl@0: ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aFsNameHash); sl@0: sl@0: for(TUint i=0; i= (TUint)iStrings.Count()) sl@0: Panic(EIndexOutOfRange); sl@0: sl@0: HBufC* des=iStrings[aIndex]; sl@0: return *des; sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Append file system name to the container. The name is converted to upper case. sl@0: @param aString name descriptor. sl@0: @return standard error code sl@0: */ sl@0: TInt XStringArray::Append(const TDesC& aString) sl@0: { sl@0: HBufC* pBuf = aString.Alloc(); sl@0: if(!pBuf) sl@0: return KErrNoMemory; sl@0: sl@0: //-- string being appended shall be unique sl@0: for(TUint i=0; iDes().UpperCase(); //-- convert the FS name to upper-case in order to correctly calculate hash later sl@0: return iStrings.Append(pBuf); sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Get child FS name hash by index in the names container. sl@0: @param aIndex name index in the container sl@0: @return file system name hash (crc32) sl@0: */ sl@0: TUint32 XStringArray::GetStringHash(TUint aIndex) const sl@0: { sl@0: const TDesC& des = operator[](aIndex); sl@0: return TVolFormatParam::CalcFSNameHash(des); sl@0: } sl@0: sl@0: sl@0: sl@0: void XStringArray::Panic(TPanicCode aPanicCode) const sl@0: { sl@0: _LIT(KPanicCat,"XStringArray"); sl@0: User::Panic(KPanicCat, aPanicCode); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: