// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).// All rights reserved.// This component and the accompanying materials are made available// under the terms of the License "Eclipse Public License v1.0"// which accompanies this distribution, and is available// at the URL "http://www.eclipse.org/legal/epl-v10.html".//// Initial Contributors:// Nokia Corporation - initial contribution.//// Contributors://// Description:// f32\sfile\sf_fmt.cpp// //#include "sf_std.h"LOCAL_C CFormatCB* GetFormatFromHandle(TInt aHandle,CSessionFs* aSession)//// Get the format control block from aHandle// { return((CFormatCB*)(SessionObjectFromHandle(aHandle,Formats->UniqueID(),aSession))); }/**Default constructor.*/EXPORT_C CFormatCB::CFormatCB() { }/** Destructor. Frees resources before destruction of the object.*/EXPORT_C CFormatCB::~CFormatCB() { if (iMount) { RemoveDiskAccess(*iMount); iMount->Drive().SetChanged(ETrue); iMount->Close(); } }/** Checks that the disk media is still mounted. @return KErrNone if the media is still mounted; KErrDisMounted otherwise.*/EXPORT_C TInt CFormatCB::CheckMount() { TDrive& d=Drive(); TInt r=d.CheckMount(); if (r!=KErrNone) return(r); if (&Mount()!=&d.CurrentMount()) return(KErrDisMounted); return(KErrNone); }void CFormatCB::InitL(TDrive* aDrive,TFormatMode aMode) { DoInitL(aDrive->DriveNumber()); iDrive=aDrive; iMount=&iDrive->CurrentMount(); iMode=aMode; User::LeaveIfError(iMount->Open()); }EXPORT_C TInt CFormatCB::GetInterface(TInt /*aInterfaceId*/,TAny*& /*aInterface*/,TAny* /*aInput*/) { return(KErrNotSupported); }//----------------------------------------------------------------------------/** set volume formatting parameters, which are provided in TLDFormatInfo structure @param apLDFormatInfo pointer to the parameters structure. If NULL, iSpecialInfo will be initialised*/void CFormatCB::SetFormatParameters(const TLDFormatInfo* apLDFormatInfo) { TLDFormatInfo& fmtInfo = iSpecialInfo(); if(!apLDFormatInfo) {//-- special meaning; invalidate iSpecialInfo by setting its package size as 0 iSpecialInfo.SetLength(0); } else { Mem::Copy(&fmtInfo, apLDFormatInfo, sizeof(TLDFormatInfo)); } }//----------------------------------------------------------------------------/** set volume formatting parameters, which are provided in TVolFormatParam structure */TInt CFormatCB::SetFormatParameters(const TVolFormatParam* apVolFormatParam) { ASSERT(apVolFormatParam); TAny* dummy; //-- push parameters to the particular implementation of the CFormatCB. Default behaviour: KErrNotSupported return GetInterface(ESetFmtParameters, dummy, (TAny*)apVolFormatParam); }//----------------------------------------------------------------------------#ifdef _DEBUG#define DUMP_OPENED_OBJECTS#endif/** Debug helper method. Dumps names of opened files and directories on this drive define DUMP_OPENED_OBJECTS to have it called*/#ifdef DUMP_OPENED_OBJECTSstatic void DumpOpenedObjects(TDrive& aDrive) { {//-- 1. files const TInt nFiles = Files->Count(); for(TInt i=0; i<nFiles; ++i) { CFileCB* pFile=(CFileCB*)(*Files)[i]; if(pFile->Drive().DriveNumber() == aDrive.DriveNumber()) { __PRINT1(_L("FsFormatOpen() opened file:'%S'"), &pFile->FileName()); } } } {//-- 2. directories; CDirCB doesn't have associated name. const TInt nDirs = Dirs->Count(); TInt cntDirs = 0; for(TInt i=0; i<nDirs; ++i) { CDirCB* pDir = (CDirCB*)(*Dirs)[i]; if(pDir->Drive().DriveNumber() == aDrive.DriveNumber()) { ++cntDirs; } } if(cntDirs) { __PRINT1(_L("FsFormatOpen() opened directories:%d"), cntDirs); } } }#endif //DUMP_OPENED_OBJECTS//----------------------------------------------------------------------------/** Open a drive for formatting.*/TInt FsFormatOpen(CFsRequest* aRequest) { TDrive& drive = *aRequest->Drive(); __PRINT1(_L("FsFormatOpen() drv:%d"), drive.DriveNumber()); TInt nMountRes = drive.CheckMount(); //-- KErrNotReady means that there is no file system mounted on this drive //-- KErrInUse means that there are some "disk access" objects, like RFormat or RRawDisk opened on the mount. if(nMountRes == KErrNotReady || nMountRes == KErrInUse) { __PRINT1(_L("FsFormatOpen() ChkMount:%d"), nMountRes); return nMountRes; } const TFormatMode fmtMode = (TFormatMode)aRequest->Message().Int1(); TName buf; TUint32 currFsNameHash = 0; //-- current file system name hash, 0 means "not set"; used during forced FS dismounting if((nMountRes == KErrNone) && drive.CurrentMount().LockStatus() < 0) {//-- the mount is locked, it has normal objects (files, directories) opened on it. //-- if someone is interested in the list of opened files and number of opened directories, compile this code in. #ifdef DUMP_OPENED_OBJECTS DumpOpenedObjects(drive); #endif //DUMP_OPENED_OBJECTS if(!(fmtMode & EForceFormat)) { __PRINT(_L("FsFormatOpen() The mount is in use")); return KErrInUse; } //-- there is a special flag that tells to force media dismounting even if it has files or dirs opened. __PRINT(_L("FsFormatOpen() The mount is in use, forcing dismounting!")); //-- record currently mounted FS name hash, it may be used after forced dismounting drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive currFsNameHash = TVolFormatParam::CalcFSNameHash(buf); //-- kill the current mount FsThreadManager::LockDrive(drive.DriveNumber()); TInt nRes = drive.ForceUnmountFileSystemForFormatting(); FsThreadManager::UnlockDrive(drive.DriveNumber()); switch(nRes) { case KErrInUse: __PRINT(_L("FsFormatOpen() The mount has clamps! Can't force dismount")); return KErrInUse; //-- there are clamps on this drive - can't dismount case KErrNone: break; default: ASSERT(0); //-- unexpected error code return nRes; }; if(fmtMode & EQuickFormat) {//-- quick format may require the normally mounted FS, make the best effrot to mount it nMountRes = drive.CheckMount(); } else {//-- this will make the FS mounted by force; for full format it will be quicker nMountRes = KErrCorrupt; } } //-- if True, we will need mount (probably specific) file system by force because normal mounting has failed TBool bNeedForceMount = (nMountRes != KErrNone); //-- find out if we have optional data structure that describes format parameter TUint32 newFsNameHash = 0; //-- file system name hash, may be used for selecting which file system to put onto the volume. 0 means "not specified" const TLDFormatInfo* pLDFormatInfo = NULL; const TVolFormatParam* pVolFormatParam = NULL; __ASSERT_COMPILE(sizeof(TVolFormatParam) >= sizeof(TLDFormatInfo)); TBuf8<sizeof(TVolFormatParam)> paramBuf; if(fmtMode & ESpecialFormat) { //-- the user has provided format parameters structure. //-- IPC argument #2 contains a structure: <TUint32>[optional package descriptor] //-- where 1st mandatory TUint32 is a pointer to format counter and the optional additional package is a data structure passed to the filesystem by the client of RFormat const TInt desLen = aRequest->GetDesLength(KMsgPtr2); ASSERT((TUint32)desLen >= sizeof(TUint32)); const TInt dataPckgLen = desLen - sizeof(TUint32); if((TUint32)dataPckgLen > sizeof(TUint32)) { aRequest->ReadL(KMsgPtr2, paramBuf); } if(dataPckgLen == sizeof(TLDFormatInfo)) {//-- the user has provided formatting parameters via TLDFormatInfo structure. pLDFormatInfo = (const TLDFormatInfo*)(paramBuf.Ptr() + sizeof(TUint32)); } else if(dataPckgLen == sizeof(TVolFormatParam)) {//-- it's likely to be TVolFormatParam, need to check UId to be sure. pVolFormatParam = (const TVolFormatParam*)(const TVolFormatParam*)(paramBuf.Ptr() + sizeof(TUint32)); if(pVolFormatParam->iUId == TVolFormatParam::KUId) //-- check the class UID {//-- this is the real TVolFormatParam object passed newFsNameHash = pVolFormatParam->FSNameHash(); } } else if(dataPckgLen >0) {//-- parameters data structure has strange length return KErrArgument; } } //------------------- if(!newFsNameHash && currFsNameHash) {//-- new file system name isn't specified (default formatting), but the volume had been forcedly dismounted. //-- restore the original file system newFsNameHash = currFsNameHash; } if(newFsNameHash) {//-- check if the specified FS is already mounted on the volume if(!bNeedForceMount) { drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive } else { //-- the iCurrentMount can be NULL, use the iFsys - the real file system associated with this drive buf = drive.GetFSys()->Name(); } const TUint32 currFSNameHash = TVolFormatParam::CalcFSNameHash(buf); if(currFSNameHash == newFsNameHash) {//-- no need to do anything, the required FS is already mounted newFsNameHash = 0; } } if(newFsNameHash) { //-- the user has specified some filesystem to be mounted on the volume. Check if this FS is supported at all. //-- if it is supported, but some other FS is currently mounted, it will be dismounted and the new one will be forced. TInt nRes; for(TInt cntFS=0; ;++cntFS) { nRes = drive.FSys().GetSupportedFileSystemName(cntFS, buf); //-- enumerate possible child file systems if(nRes != KErrNone) return KErrNotSupported; //-- the filesystem with the given name (fsNameHash) is not supported. if(newFsNameHash == TVolFormatParam::CalcFSNameHash(buf)) {//-- the filesystem with the given name (fsNameHash) is supported, but some other filesystem can be already mounted drive.Dismount(); bNeedForceMount = ETrue; //-- this will force the desired FS to be mounted break; } } }//if(fsNameHash) //-- try force mounting the desired file system if it is required if(bNeedForceMount) { const TInt KMaxRetries = 3; for(TInt cnt=0; ; ++cnt) { drive.MountFileSystem(ETrue, newFsNameHash); nMountRes = drive.GetReason(); if(nMountRes == KErrNone || nMountRes == KErrLocked) break; drive.Dismount(); //-- will reset mount retries counter if(cnt >= KMaxRetries) { __PRINT1(_L("FsFormatOpen() can't mount FS! res:%d"), nMountRes); return nMountRes; } } } ASSERT(nMountRes == KErrNone || nMountRes == KErrLocked); __ASSERT_DEBUG(drive.CurrentMount().LockStatus()==0, Fault(ESvrFormatOpenFailed)); TDriveInfo dInfo; drive.DriveInfo(dInfo); const TInt mediaAtt = dInfo.iMediaAtt;#if defined(_LOCKABLE_MEDIA) if (!(fmtMode & EForceErase) && (mediaAtt & KMediaAttLocked)) { // if attempting to format a locked drive, dismount otherwise subsequent // requests will operate on a mount that has been forcibly mounted (a few lines above) CMountCB* pM = &drive.CurrentMount(); if(pM) pM->Close(); drive.MountFileSystem(EFalse); // clear iCurrentMount return KErrLocked; }#endif if (!(mediaAtt & KMediaAttFormattable) || (mediaAtt & KMediaAttWriteProtected)) { CMountCB* pM = &drive.CurrentMount(); if(pM) pM->Close(); drive.MountFileSystem(EFalse); return KErrAccessDenied; } //-- instantinate and open CFormatCB object for this drive CFormatCB* formatCB=NULL; TInt fmtHandle; TRAPD(ret, formatCB = drive.FormatOpenL(aRequest, fmtHandle, fmtMode, pLDFormatInfo, pVolFormatParam )); if (ret!=KErrNone) { if(formatCB) formatCB->Close(); return ret; } TPtrC8 pH((TUint8*)&fmtHandle,sizeof(TInt)); aRequest->WriteL(KMsgPtr3,pH); TInt count=100; TPtrC8 pCount((TUint8*)&count,sizeof(TInt)); aRequest->WriteL(KMsgPtr2,pCount); aRequest->Session()->IncResourceCount(); return KErrNone; }TInt TFsFormatOpen::DoRequestL(CFsRequest* aRequest)//// Open a drive for formatting.// { // Can not format if any files are clamped TInt r=FsFormatOpen(aRequest); return r; }TInt TFsFormatOpen::Initialise(CFsRequest* aRequest)////// { TInt r; if (!KCapFsFormatOpen.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Format Open"))) return KErrPermissionDenied; r=ParseNoWildSubstPtr0(aRequest,aRequest->Src()); if (r!=KErrNone) return(r); if (aRequest->Src().NameOrExtPresent()) return(KErrBadName); if (aRequest->SubstedDrive()) return(KErrAccessDenied); return(r); }TInt TFsFormatNext::DoRequestL(CFsRequest* aRequest)//// Format the next part of the media.// { __PRINT1(_L("TFsFormatNext::DoRequestL() drv:%d"), aRequest->DriveNumber()); CFormatCB* format=(CFormatCB*)aRequest->ScratchValue(); TInt r=format->CheckMount(); if (r!=KErrNone && r!=KErrInUse) { __PRINT1(_L("TFsFormatNext::DoRequestL() err:%d"), r); return r; } TPtr8 pStep((TUint8*)&format->CurrentStep(),sizeof(TInt)); aRequest->ReadL(KMsgPtr0,pStep); TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFormatCBDoFormatStepL, EF32TraceUidFileSys, format); TRAP(r,format->DoFormatStepL()); TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFormatCBDoFormatStepLRet, EF32TraceUidFileSys, r, format->CurrentStep()); if (r==KErrNone) aRequest->WriteL(KMsgPtr0,pStep); if (r==KErrNone && format->CurrentStep()==0) { FsNotify::DiskChange(aRequest->DriveNumber()); } return(r); }TInt TFsFormatNext::Initialise(CFsRequest* aRequest)////// { if (!KCapFsFormatNext.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Format Next"))) return KErrPermissionDenied; CFormatCB* format; format=GetFormatFromHandle(aRequest->Message().Int3(), aRequest->Session()); if(!format) return(KErrBadHandle); aRequest->SetDrive(&format->Drive()); aRequest->SetScratchValue((TUint)format); return KErrNone; }