diff -r d57b86b1867a -r dc268b18d709 userlibandfileserver/fileserver/automounter/automounter.cpp --- a/userlibandfileserver/fileserver/automounter/automounter.cpp Mon Sep 13 15:16:07 2010 +0100 +++ b/userlibandfileserver/fileserver/automounter/automounter.cpp Wed Sep 22 10:53:45 2010 +0100 @@ -69,6 +69,7 @@ { __PRINT1(_L("#<<- CAutoMounterFileSystem::CAutoMounterFileSystem() [0x%x]"), this); + iChildFsForDefFmt = KErrNotFound; SetState(EInvalid); } @@ -187,11 +188,11 @@ { __PRINT1(_L("#<<- CAutoMounterFileSystem::IsExtensionSupported() [0x%x]"), this); - ASSERT(State() == EInitialised && iFSNames.Count() > 1); + ASSERT(State() == EInitialised && ChildFsNum() >= KMinChildFsNum); //-- in debug mode check file systems compatibility: ALL childs must support this feature - for(TUint i=0; iIsExtensionSupported())) { @@ -258,7 +259,10 @@ //----------------------------------------------------------------------------- /** - Find out if _all_ child file systems support the proxy drive. All childs shall behave exactly the same way. + Find out if _all_ child file systems support the proxy drive. All child file systems shall behave exactly the same way. + This is mostly for the USB host drives support. All child file systems should either support this feature or do not. + Otherwise, it may lead to very obscured cases of susystem misbehaviour. + @return KErrNone if all child file systems support proxy drives, or KErrNotSupported if all of them do not. */ TInt CAutoMounterFileSystem::DoProcessProxyDriveSupport() @@ -266,9 +270,8 @@ __PRINT1(_L("#<<- CAutoMounterFileSystem::DoProcessProxyDriveSupport[0x%x]"), this); ASSERT(State() == EInitialised); - const TUint cnt = iFSNames.Count(); - ASSERT(cnt > 1); - + const TUint cnt = ChildFsNum(); + ASSERT(cnt >= KMinChildFsNum); //-- query the default filesystem #0 const TBool bRes = GetChildFileSystem(KDefaultFSNo)->IsProxyDriveSupported(); @@ -307,7 +310,7 @@ } //-- this is a query for one of the child filesystems - if((TUint)aFsNumber < iFSNames.Count()) + if((TUint)aFsNumber < ChildFsNum()) { aFsName = iFSNames[aFsNumber]; return KErrNone; @@ -324,8 +327,8 @@ In this method the automounter sequentially tries to mount every child and on success produces the corresponding CMountCB object. @param apDrive pointer to the TDrive, child FS will need this to access media. - @param apFileSystem on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if - one of the child file system has recognised the volume. + @param apFileSystem on return will contain the pointer to the CFileSystem that has produced the proper CMountCB if + one of the child file system has recognised the volume layout. @param aForceMount if ETrue the appropriate child FS (designated by aFsNameHash) will be forcedly mounted on the volume. for volume formatting purposes. @param aFsNameHash if !=0 specifies the file system name, see TVolFormatParam::CalcFSNameHash(). 0 means "file system name is not specified" @@ -344,42 +347,61 @@ if(apDrive->IsSynchronous()) Fault(EWrongDriveAttributes); - if(iFSNames.Count() < 2) + if(ChildFsNum() < KMinChildFsNum) Fault(EWrongConfiguration); //-- if aForceMount is true, this means that the TDrive tries mount the filesystem by force for formatting because normal mounting has failed before. //-- in our case it means that the file system on the volume hadn't been recognised by any child FS. //-- aFsNameHash shall designate the file system to be forcedly mounted. Depending on this the appropriat CMounCB object will be produced. - //-- if aFsNameHash is 0, i.e. not provided, this method will fail with KErrNotFound because it is impossible to select appropriat child FS. + //-- if aFsNameHash is 0, i.e. not provided, this method will fail with KErrNotFound if it can't to select appropriate child FS to be used. if(aForceMount) { + CFileSystem *pFS = NULL; //-- the FS selected to produce CMountCB for media formatting + if(aFsNameHash == 0) {//-- the file system to mount forcedly is not specified + //-- 1. check if we have only 1 child FS supported. Quite a weird case, but an easy choice. + if(ChildFsNum() == 1) + {//-- use the single known child FS + __PRINT1(_L("#<<- only 1 child FS available for formatting: %S"), &iFSNames[KDefaultFSNo]); + pFS = GetChildFileSystem(KDefaultFSNo); + } + else if(iChildFsForDefFmt >= 0) + {//-- the parameter "child fs for default formatting" is defined. try using this + __PRINT1(_L("#<<- using the default child FS for formatting: %S"), &iFSNames[iChildFsForDefFmt]); + pFS = GetChildFileSystem(iChildFsForDefFmt); + } + else + { __PRINT(_L("#<<- Unable to select appropriate child FS for formatting!")); User::Leave(KErrNotFound); } - else - {//-- try to find appropriate child FS by its name hash - CFileSystem *pFS = GetChildFileSysteByNameHash(aFsNameHash); + } + else //if(aFsNameHash == 0) + {//-- try to find appropriate child FS by its name hash provided by the upper level + pFS = GetChildFileSysteByNameHash(aFsNameHash); if(!pFS) { __PRINT(_L("#<<- no child FS found by its name hash!")); ASSERT(0); User::Leave(KErrNotFound); } + } + //-- ask the selected FS to produce us a mount for media formating + ASSERT(pFS); CMountCB* pMount = pFS->NewMountL(); ASSERT(pMount); *apFileSystem = pFS; return pMount; - } }//if(aForceMount) //-- try instantiate a new CMountCB depending on the file system on the media + ASSERT(!aForceMount); CMountCB* pMatchedMount; TInt nRes = TryMountFilesystem(apDrive, &pMatchedMount, apFileSystem); @@ -391,63 +413,30 @@ } - User::Leave(nRes); return NULL; } + //----------------------------------------------------------------------------- /** - Initialise this file system. Reads and processes configuration, fills in file system names container, etc. -*/ -void CAutoMounterFileSystem::InitialiseFileSystem() - { - __PRINT1(_L("#<<- CAutoMounterFileSystem::InitialiseFileSystem() [0x%x]"), this); - - ASSERT(State() == ENotInitialised); + Parse the string with child file system names. These names come from config, which can be either + estart.txt or a text debug property that can override it. - TInt nRes; - + @param aList string descriptor with contents like "fat,exfat" i.e. it is comma separated file system names +*/ +void CAutoMounterFileSystem::DoParseChildNames(const TDesC8& aList) + { + ASSERT(State() == EInitialising); - //-- 1. initialise the array of file system names. These names shall be listed in a config string. - //-- the config string is taken from estart.txt usually and its format is like this: - //-- section: [AutoMounter] and property "FSNames fat,exfat" - //-- in debug version a special text property can override the config string. This allows controlling automounter from - //-- the test environment. - - TBuf8<0x100> buf(0); TBuf<0x100> fsName; - -#ifdef _DEBUG - const TUid KSID_Test1={0x10210EB3}; //-- SID of the test that will define and set test property to control volume mounting - const TUint KPropKey = 0; //-- property key - - //-- in debug mode the property will override the estart.txt config - if(RProperty::Get(KSID_Test1, KPropKey, buf) == KErrNone) - { - __PRINT(_L("#<<- reading config from the debug propery...")); - } - else -#endif - { - __PRINT(_L("#<<- reading config from estart.txt...")); - _LIT8(KSection, "AutoMounter"); - _LIT8(KProperty, "FSNames"); - - nRes = F32Properties::GetString(KSection, KProperty, buf); - if(!nRes) - Fault(EPluginInitialise); - } - - - fsName.Copy(buf); - __PRINT1(_L("#<<- config:'%S'"), &fsName); + fsName.Copy(aList); + __PRINT1(_L("#<<- childFS list:'%S'"), &fsName); //-- parse CSV config line and fill in the file system names array const TChar chDelim = ','; //-- token delimiter, comma - buf.Trim(); - TPtrC8 ptrCurrLine(buf); + TPtrC8 ptrCurrLine(aList); for(TInt i=0; ;++i) { const TInt delimPos = ptrCurrLine.Locate(chDelim); @@ -478,7 +467,8 @@ } - nRes = iFSNames.Append(fsName); + TInt nRes = iFSNames.Append(fsName); + (void)nRes; ASSERT(nRes ==KErrNone); if(delimPos <=0 ) @@ -487,14 +477,203 @@ ptrCurrLine.Set(ptrCurrLine.Ptr()+delimPos+1, ptrCurrLine.Length()-delimPos-1); } + } + +//----------------------------------------------------------------------------- + +//-- if this macro is defined, the automounter will use a default hard-coded list of child file systems if it is not found in the estart.txt +//-- and this list will consist of one filesystem "FAT". +//-- otherwise automounter will panic if it can't find appropriate config in estart.txt +#define ALLOW_CONFIGLESS + +/** + Process Automounter configuration +*/ +void CAutoMounterFileSystem::ParseConfig() + { + + + ASSERT(State() == ENotInitialised); + + SetState(EInitialising); + + + + //-- 1. initialise the array of file system names. These names shall be listed in a config string. + //-- the config string is taken from estart.txt usually and its format is like this: + //-- section: [AutoMounter] and property "AM_FSNames fat,exfat" + //-- in debug version a special text property can override the config string. This allows controlling automounter from + //-- the test environment. + + TBuf8<0x100> buf(0); + + _LIT8(KSection, "AutoMounter"); ///< section name + _LIT8(KKey_ChildFsList, "AM_FSNames"); ///< a key for the CSV list of child file system names + _LIT8(KProp_DefFmtFsIdx, "AM_DefFmtFsIdx");///< a key for the optional parameter that specifies the child file system index, which will be used for formatting unrecognised media + + TBool bUseEstart= ETrue; + +#ifdef _DEBUG + + TInt nRes; + + const TUid KSID_Test1={0x10210EB3}; //-- SID of the test that will define and set test property to control volume mounting + const TUint KPropKey = 0; //-- property key + + //-- in debug mode the property will override the estart.txt config + if(RProperty::Get(KSID_Test1, KPropKey, buf) == KErrNone) + { + __PRINT(_L("#<<- reading config from the debug propery:")); + TBuf<0x100> buf16(0); + buf16.Copy(buf); + __PRINT(buf16); + + bUseEstart = EFalse; + } +#endif //_DEBUG + + if(bUseEstart) + {//-- need to read data from the estart.txt, section [AutoMounter] + __PRINT(_L("#<<- reading config from estart.txt...")); + + //-- 1. read and parse a CSV list of child file system names + //-- this is a mandatory parameter + TBool bFound = F32Properties::GetString(KSection, KKey_ChildFsList, buf); + if(!bFound) + { + __PRINT(_L("#<<- child FS list isn't found in config !")); + + #ifdef ALLOW_CONFIGLESS + //-- let's use a default list of child file systems (consisting of only one: "FAT") + //-- if it is allowed. FAT FS is suggested to be available and already loaded by file server. + //-- otherwise it will panic later + + _LIT(KDefChildFS_Config, "fat"); //-- default list + __PRINT1(_L("#<<- Using a default list:'%S'"), &KDefChildFS_Config()); + buf.Copy(KDefChildFS_Config); + + #else //ALLOW_CONFIGLESS + + Fault(EPluginInitialise); + + #endif //ALLOW_CONFIGLESS + } + + DoParseChildNames(buf); + + ASSERT(iFSNames.Count()); + + //-- 2. read a child FS index that can be used for unrecognisable media default formatting + //-- this is an optional parameter. If we have just 1 Child FS, this parameter doesn't make much sense. + if(iFSNames.Count() > 1) + { + TInt32 nVal; + bFound = F32Properties::GetInt(KSection, KProp_DefFmtFsIdx, nVal); + + if(!bFound) + iChildFsForDefFmt = KErrNotFound; + else + {//-- check the index validity + if(nVal <0 || nVal >= (TInt)iFSNames.Count()) + { + __PRINT1(_L("#<<- Bad DefFmtFsIdx value:%d"), nVal); + Fault(EPluginInitialise); + } + else + { + iChildFsForDefFmt = nVal; + } + } + } + else//if(iFSNames.Count() > 1) + {//-- it looks like we have a weird case when the automounter is configured with just 1 child file system + iChildFsForDefFmt = KDefaultFSNo; + } + + }//if(bUseEstart) + else + { +#ifdef _DEBUG + + //-- it looks like there is a test property that overrides the estart.txt settings. This property should contain + //-- a representation of a whole [AutoMounter] section in estart.txt and can have "multiple lines" separated by 0x0d,0x0a + buf.TrimAll(); + + TInt nPos1; + TInt nPos2; + + //-- 1. process "AM_FSNames" key + nPos1 = buf.FindF(KKey_ChildFsList); + if(nPos1 < 0) + { + __PRINT(_L("#<<- child FS list isn't found!")); + Fault(EPluginInitialise); + } + + TPtrC8 ptr(buf.Mid(nPos1)); + nPos2 = ptr.Locate('\n'); + if(nPos2 > 0) + ptr.Set(ptr.Left(nPos2)); + + TLex8 lex(ptr); + + lex.NextToken(); + lex.SkipSpace(); + ptr.Set(lex.Remainder()); + + DoParseChildNames(ptr); + ASSERT(iFSNames.Count()); + + + //-- 2. process "DefFmtFsIdx" key + nPos1 = buf.FindF(KProp_DefFmtFsIdx); + if(nPos1 > 0 && iFSNames.Count() > 1) + { + ptr.Set(buf.Mid(nPos1)); + nPos2 = ptr.Locate('\n'); + if(nPos2 > 0) + ptr.Set(ptr.Left(nPos2)); + + lex.Assign(ptr); + lex.NextToken(); + lex.SkipSpace(); + + nRes = lex.Val(nPos1); + ASSERT(nRes == KErrNone); + ASSERT(nPos1 >= 0 && nPos1 < (TInt)iFSNames.Count()); + + iChildFsForDefFmt = nPos1; + } + else + { + iChildFsForDefFmt = KErrNotFound; + } + +#endif //_DEBUG + } + + } + + +//----------------------------------------------------------------------------- +/** + Initialise this file system. Reads and processes configuration, fills in file system names container, etc. +*/ +void CAutoMounterFileSystem::InitialiseFileSystem() + { + __PRINT1(_L("#<<- CAutoMounterFileSystem::InitialiseFileSystem() [0x%x]"), this); + + ASSERT(State() == ENotInitialised); + + ParseConfig(); SetState(EInitialised); //-- 2. check that the file server has all filesystems we need instantiated and stored in a global container - TUint cnt = iFSNames.Count(); - if(cnt < 2) + TUint cnt = ChildFsNum(); + if(cnt < KMinChildFsNum) { - __PRINT(_L("#<<- ::InitialiseFileSystem(): too few File Systems bound!")); + __PRINT1(_L("#<<- ::InitialiseFileSystem(): too few File Systems bound: %d!"), cnt); Fault(EPluginInitialise); } @@ -523,9 +702,8 @@ { __PRINT1(_L("#<<- CAutoMounterFileSystem::TryMountFilesystem()[0x%x]"), this); - const TInt KNumFS = iFSNames.Count(); - - ASSERT(State() == EInitialised && (KNumFS >1)); + const TUint KNumFS = ChildFsNum(); //-- number of child file systems supported + ASSERT(State() == EInitialised && (KNumFS >= KMinChildFsNum)); *apMount = NULL; @@ -533,7 +711,7 @@ TInt nRes; - TInt cntFS; + TUint cntFS; CMountCB* pMountCB = NULL; CFileSystem* pMatchedFS = NULL; @@ -550,7 +728,7 @@ TRAP(nRes, pMountCB = pFS->NewMountL()); if(nRes != KErrNone) { - return KErrNoMemory; + return nRes; } ASSERT(pMountCB); @@ -626,7 +804,7 @@ */ CFileSystem* CAutoMounterFileSystem::GetChildFileSystem(TUint aIndex) const { - ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aIndex < iFSNames.Count()); + ASSERT(State() == EInitialised && (ChildFsNum() >= KMinChildFsNum) && aIndex < ChildFsNum()); const TDesC& fsName = iFSNames[aIndex]; //-- registered child file system name CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container @@ -648,9 +826,10 @@ */ CFileSystem* CAutoMounterFileSystem::GetChildFileSysteByNameHash(TUint32 aFsNameHash) const { - ASSERT(State() == EInitialised && (iFSNames.Count() >1) && aFsNameHash); + ASSERT(State() == EInitialised && (ChildFsNum() >= KMinChildFsNum) && aFsNameHash); - for(TUint i=0; i