diff -r d57b86b1867a -r dc268b18d709 userlibandfileserver/fileserver/sfsrv/cl_drive.cpp --- a/userlibandfileserver/fileserver/sfsrv/cl_drive.cpp Mon Sep 13 15:16:07 2010 +0100 +++ b/userlibandfileserver/fileserver/sfsrv/cl_drive.cpp Wed Sep 22 10:53:45 2010 +0100 @@ -125,3 +125,392 @@ return driveName; } + + +//------------------------------------------------------------------------------------------------------------------- + +/** + internal class of the CFsMountHelper, provides the real implementation, It is not supposed to + be instantiated by anyone except CFsMountHelper. +*/ +class TFsMntHelperImpl + { + friend class CFsMountHelper; + + private: + + TFsMntHelperImpl(RFs& aFs, TInt aDrvNum); + + //------ 1:1 interface to the host CFsMountHelper class + void Init(); + TInt GetMountProperties(); + TInt MountFileSystem() const; + void DismountFileSystem(TRequestStatus& aStat, CFsMountHelper::TFsDismountMode aDismountMode) const; + //------ + + private: + TBool DataValid() const {return iFsName.Length() >0;} + TBool operator==(const TFsMntHelperImpl& aRhs) const; + + enum {KPrimExtIdx =0}; //-- index of the primary extension name in the iExtNames array + + const TDesC& FSysName() const {return iFsName;} + const TDesC& PrimaryExtName() const {return iExtNames[KPrimExtIdx];} + + /** bits in a error bitmap that indicate some, potentially multiple, API failure reasons */ + enum TErrorBits + { + Err_GetFsName = 0x0001, ///< Error when trying to obtain FS name (possible reason: there is no FS at all on this drive) + Err_MountFs = 0x0002, ///< Error when mounting the FS. (possible reason: the FS layout on the media is corrupt or not recognised) + Err_MountFsPrimExt = 0x0004, ///< Error when mounting the FS with the primary extension + Err_MountSecExt = 0x0008, ///< Error when mounting the secondary extension + }; + + + void AddErrorBit(TUint32 aFlag) const {ASSERT(aFlag); iErrorBitmap |= aFlag;} + + /** panic codes */ + enum TPanicCode + { + ENotInitialised, ///< the instance of the implementation is not created + EDrvNumberInvalid,///< invalid drive number provided + ENotImplemented ///< the functionality is not implemented + }; + + void Panic(TPanicCode aPanicCode) const; + + private: + RFs& iFs; ///< reference to the file server session + TInt iDrvNum; ///< drive number + TFSName iFsName; ///< file system name. + TFSName iExtNames[KMaxExtensionCount]; ///< [0] is a primary ext. name + up to several secondary ones + TBool iDrvSynch; ///< true if the drive is synchronous + mutable TUint32 iErrorBitmap; ///< 32 bits indicating API call failures. '1' bit corresponds to some particular reason. See TErrorBits. + }; + + +//------------------------------------------------------------------------------------------------------------------- + +void TFsMntHelperImpl::DismountFileSystem(TRequestStatus& aStat, CFsMountHelper::TFsDismountMode aDismountMode) const + { + if(!this) + Panic(ENotInitialised); + + TInt nRes; + +#ifdef _DEBUG + //-- consistency check (debug mode only). Check that we are dismounting file system with the same parameters + //-- since last GetMountProperties() call + TFsMntHelperImpl currSnapshot(iFs, iDrvNum); + currSnapshot.GetMountProperties(); + ASSERT(currSnapshot == *this); + +#endif //_DEBUG + + + nRes = KErrArgument; + TRequestStatus* pStat = &aStat; + + switch(aDismountMode) + { + case CFsMountHelper::ENormal: + //-- normal graceful dismounting. Will fail with KErrInUse if there are any opened objects, like files, directories etc. + //-- aStat is completed with the API return code. + nRes = iFs.DismountFileSystem(iFsName, iDrvNum); + User::RequestComplete(pStat, nRes); + break; + + case CFsMountHelper::EForceImmediate: + //-- immediate forced dismount. Don't pay attention to any opened objects. All handles will become invalid. + //-- The user should wait for aStat completion. Though it is very likely that it is completed immediately. + iFs.NotifyDismount(iDrvNum, aStat, EFsDismountForceDismount); + break; + + + case CFsMountHelper::ENotifyClients: + //-- attempt to dismount FS with notifying any interested clients. + iFs.NotifyDismount(iDrvNum, aStat, EFsDismountNotifyClients); + break; + + default: + ASSERT(0); + User::RequestComplete(pStat, KErrArgument); + break; + }; + + } + + +//------------------------------------------------------------------- +TInt TFsMntHelperImpl::GetMountProperties() + { + if(!this) + Panic(ENotInitialised); + Init(); + + TInt nRes; + + //-- 1. get file system name + nRes = iFs.FileSystemName(iFsName, iDrvNum); + if(nRes != KErrNone) + { + AddErrorBit(Err_GetFsName); //-- indicate an error + return nRes; + } + + //-- 2. find out if the drive sync/async + TPckgBuf drvSyncBuf; + nRes = iFs.QueryVolumeInfoExt(iDrvNum, EIsDriveSync, drvSyncBuf); + if(nRes != KErrNone) + {//-- pretend that the drive is asynch. in the case of file system being corrupted. this is 99.9% true + iDrvSynch = EFalse; + } + else + { + iDrvSynch = drvSyncBuf(); + } + + //-- 3. find out extension names if there are any. Extension #0 is a primary one and up to several secondary ones + for(TInt i=0; i0); + + //-- all possible extensions that have existed before dismounting should be present in the file server context. + //-- anyway, it's impossible to load them here, because their file names are unknown + + if(bPrimaryExtExists) + {//-- there was a primary extension, use special mounting API + nRes = iFs.MountFileSystem(FSysName(), PrimaryExtName(), iDrvNum, iDrvSynch); + } + else + { + nRes = iFs.MountFileSystem(FSysName(), iDrvNum, iDrvSynch); + } + + //-- actually, if nRes != KErrNone, it doesn't _necessarily_ mean that _mounting_ of the file system failed. + //-- for example, the FS can be bound to the drive OK, but the media can be corrupted. This can happen when the FS + //-- had been dismounted from such a corrupted media. + //-- opposite, KErrNotReady is very likely to mean that the removable media is not present. + + const TInt nFsMountRes = nRes; + if(nFsMountRes != KErrNone) + { + AddErrorBit(bPrimaryExtExists ? Err_MountFsPrimExt : Err_MountFs); + } + + //-- mount secondary extensions if there were any + TInt nExtMountRes = KErrNone; + for(TInt i=1; i0) + { + nRes = iFs.MountExtension(iExtNames[i], iDrvNum); + if(nRes != KErrNone) + {//-- indicate that an error happened while installing some secondary extension + AddErrorBit(Err_MountSecExt); + nExtMountRes = nRes; + } + } + } + + //-- return FS mounting error code if it wasn't OK, otherwise - extension mounting code. + //-- for more info see error bitmap + return (nFsMountRes != KErrNone) ? nFsMountRes : nExtMountRes; + } + +//------------------------------------------------------------------- +void TFsMntHelperImpl::Init() + { + if(!this) + Panic(ENotInitialised); + + iDrvSynch = EFalse; + iFsName.Zero(); + iErrorBitmap = 0; + + for(TInt i=0; iEDriveZ) + Panic(EDrvNumberInvalid); + + Init(); + } + +/** + Debug only method. Compares 2 instances of the implementation +*/ +TBool TFsMntHelperImpl::operator==(const TFsMntHelperImpl& aRhs) const + { + ASSERT(this != &aRhs); + +#ifdef _DEBUG + + + if(iFsName.CompareF(aRhs.iFsName) !=0) + return EFalse; + + for(TInt i=0; iipImpl = new TFsMntHelperImpl(aFs, aDrvNum); + + if(!pSelf->ipImpl) + { + delete pSelf; + pSelf = NULL; + } + } + + return pSelf; +} + +//------------------------------------------------------------------- +/** + Closes the object, deletes the implementation +*/ +EXPORT_C void CFsMountHelper::Close() +{ + delete ipImpl; + ipImpl = NULL; +} + + +//------------------------------------------------------------------- +/** + Acqires drive/mount/file system properties that will be used for mounting the file system back. + @return Standard Error code. +*/ +EXPORT_C TInt CFsMountHelper::GetMountProperties() + { + return ipImpl->GetMountProperties(); + } + +//------------------------------------------------------------------- +/** + Mount the file system onto the drive using properties previously acquired by GetMountProperties() call. + Note that the drive shouldn't have the file system mounted, this API call will fail in this case. + + @return KErrNone if mounting file system + possible extensions was ok + the result of file system mounting if the file system mounting failed (e.g. because of the damaged media) + the result of mounting secondary extension if file system mounted OK, but secondary extension mounting resulted in some error. +*/ +EXPORT_C TInt CFsMountHelper::MountFileSystem() const + { + return ipImpl->MountFileSystem(); + } + +//------------------------------------------------------------------- + +/** + An asynchronous API to dismount the file system on the specified drive. + Precondition: The drive / file system parameters at the time of this API call must be the same as acquired by the last call of GetMountProperties(). + This is checked in debug mode to prevent possible inconsistencied when mounting the file system back later. + This means that the GetMountProperties() should be called at least once before any attempt to dismount the file system. + + @param aStat request status. On completion will contain the dismounting result code. + @param aDismountMode describes the dismounting method. See TFsDismountMode. + + +*/ +EXPORT_C void CFsMountHelper::DismountFileSystem(TRequestStatus& aStat, TFsDismountMode aDismountMode/*=ENormal*/) const + { + ipImpl->DismountFileSystem(aStat, aDismountMode); + } + + +//------------------------------------------------------------------- +/** + A simplified synchronous version of the DismountFileSystem() API. + Works absolutely the same as RFs::DismountFileSystem() + + @return RFs::DismountFileSystem() result code +*/ +EXPORT_C TInt CFsMountHelper::DismountFileSystem() const + { + TRequestStatus stat; + DismountFileSystem(stat, ENormal); + User::WaitForRequest(stat); + + return stat.Int(); + } + + + + + +