userlibandfileserver/fileserver/automounter/automounter.cpp
changeset 271 dc268b18d709
parent 33 0173bcd7697c
--- 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; i<iFSNames.Count(); ++i)
+    for(TUint i=0; i<ChildFsNum(); ++i)
         {
         if( !(GetChildFileSystem(i)->IsExtensionSupported()))
             {
@@ -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<iFSNames.Count(); ++i)
+    const TUint cnt = ChildFsNum(); 
+    for(TUint i=0; i<cnt; ++i)
         {
         if(aFsNameHash == iFSNames.GetStringHash(i))
             {