First public contribution.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfile\sf_fmt.cpp
20 LOCAL_C CFormatCB* GetFormatFromHandle(TInt aHandle,CSessionFs* aSession)
22 // Get the format control block from aHandle
25 return((CFormatCB*)(SessionObjectFromHandle(aHandle,Formats->UniqueID(),aSession)));
33 EXPORT_C CFormatCB::CFormatCB()
42 Frees resources before destruction of the object.
44 EXPORT_C CFormatCB::~CFormatCB()
49 RemoveDiskAccess(*iMount);
50 iMount->Drive().SetChanged(ETrue);
59 Checks that the disk media is still mounted.
60 @return KErrNone if the media is still mounted; KErrDisMounted otherwise.
62 EXPORT_C TInt CFormatCB::CheckMount()
66 TInt r=d.CheckMount();
69 if (&Mount()!=&d.CurrentMount())
70 return(KErrDisMounted);
74 void CFormatCB::InitL(TDrive* aDrive,TFormatMode aMode)
76 DoInitL(aDrive->DriveNumber());
78 iMount=&iDrive->CurrentMount();
80 User::LeaveIfError(iMount->Open());
84 EXPORT_C TInt CFormatCB::GetInterface(TInt /*aInterfaceId*/,TAny*& /*aInterface*/,TAny* /*aInput*/)
86 return(KErrNotSupported);
90 //----------------------------------------------------------------------------
92 set volume formatting parameters, which are provided in TLDFormatInfo structure
93 @param apLDFormatInfo pointer to the parameters structure. If NULL, iSpecialInfo will be initialised
95 void CFormatCB::SetFormatParameters(const TLDFormatInfo* apLDFormatInfo)
97 TLDFormatInfo& fmtInfo = iSpecialInfo();
100 {//-- special meaning; invalidate iSpecialInfo by setting its package size as 0
101 iSpecialInfo.SetLength(0);
105 Mem::Copy(&fmtInfo, apLDFormatInfo, sizeof(TLDFormatInfo));
109 //----------------------------------------------------------------------------
110 /** set volume formatting parameters, which are provided in TVolFormatParam structure */
111 TInt CFormatCB::SetFormatParameters(const TVolFormatParam* apVolFormatParam)
113 ASSERT(apVolFormatParam);
115 //-- push parameters to the particular implementation of the CFormatCB. Default behaviour: KErrNotSupported
116 return GetInterface(ESetFmtParameters, dummy, (TAny*)apVolFormatParam);
119 //----------------------------------------------------------------------------
121 #define DUMP_OPENED_OBJECTS
125 Debug helper method. Dumps names of opened files and directories on this drive
126 define DUMP_OPENED_OBJECTS to have it called
128 #ifdef DUMP_OPENED_OBJECTS
129 static void DumpOpenedObjects(TDrive& aDrive)
132 const TInt nFiles = Files->Count();
133 for(TInt i=0; i<nFiles; ++i)
135 CFileCB* pFile=(CFileCB*)(*Files)[i];
136 if(pFile->Drive().DriveNumber() == aDrive.DriveNumber())
138 __PRINT1(_L("FsFormatOpen() opened file:'%S'"), &pFile->FileName());
144 {//-- 2. directories; CDirCB doesn't have associated name.
145 const TInt nDirs = Dirs->Count();
147 for(TInt i=0; i<nDirs; ++i)
149 CDirCB* pDir = (CDirCB*)(*Dirs)[i];
150 if(pDir->Drive().DriveNumber() == aDrive.DriveNumber())
158 __PRINT1(_L("FsFormatOpen() opened directories:%d"), cntDirs);
164 #endif //DUMP_OPENED_OBJECTS
166 //----------------------------------------------------------------------------
168 Open a drive for formatting.
170 TInt FsFormatOpen(CFsRequest* aRequest)
172 TDrive& drive = *aRequest->Drive();
174 __PRINT1(_L("FsFormatOpen() drv:%d"), drive.DriveNumber());
176 TInt nMountRes = drive.CheckMount();
177 //-- KErrNotReady means that there is no file system mounted on this drive
178 //-- KErrInUse means that there are some "disk access" objects, like RFormat or RRawDisk opened on the mount.
179 if(nMountRes == KErrNotReady || nMountRes == KErrInUse)
181 __PRINT1(_L("FsFormatOpen() ChkMount:%d"), nMountRes);
185 const TFormatMode fmtMode = (TFormatMode)aRequest->Message().Int1();
187 TUint32 currFsNameHash = 0; //-- current file system name hash, 0 means "not set"; used during forced FS dismounting
189 if((nMountRes == KErrNone) && drive.CurrentMount().LockStatus() < 0)
190 {//-- the mount is locked, it has normal objects (files, directories) opened on it.
192 //-- if someone is interested in the list of opened files and number of opened directories, compile this code in.
193 #ifdef DUMP_OPENED_OBJECTS
194 DumpOpenedObjects(drive);
195 #endif //DUMP_OPENED_OBJECTS
198 if(!(fmtMode & EForceFormat))
200 __PRINT(_L("FsFormatOpen() The mount is in use"));
204 //-- there is a special flag that tells to force media dismounting even if it has files or dirs opened.
205 __PRINT(_L("FsFormatOpen() The mount is in use, forcing dismounting!"));
207 //-- record currently mounted FS name hash, it may be used after forced dismounting
208 drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
209 currFsNameHash = TVolFormatParam::CalcFSNameHash(buf);
211 //-- kill the current mount
212 FsThreadManager::LockDrive(drive.DriveNumber());
213 TInt nRes = drive.ForceUnmountFileSystemForFormatting();
214 FsThreadManager::UnlockDrive(drive.DriveNumber());
220 __PRINT(_L("FsFormatOpen() The mount has clamps! Can't force dismount"));
221 return KErrInUse; //-- there are clamps on this drive - can't dismount
227 ASSERT(0); //-- unexpected error code
232 if(fmtMode & EQuickFormat)
233 {//-- quick format may require the normally mounted FS, make the best effrot to mount it
234 nMountRes = drive.CheckMount();
237 {//-- this will make the FS mounted by force; for full format it will be quicker
238 nMountRes = KErrCorrupt;
243 //-- if True, we will need mount (probably specific) file system by force because normal mounting has failed
244 TBool bNeedForceMount = (nMountRes != KErrNone);
246 //-- find out if we have optional data structure that describes format parameter
247 TUint32 newFsNameHash = 0; //-- file system name hash, may be used for selecting which file system to put onto the volume. 0 means "not specified"
249 const TLDFormatInfo* pLDFormatInfo = NULL;
250 const TVolFormatParam* pVolFormatParam = NULL;
252 __ASSERT_COMPILE(sizeof(TVolFormatParam) >= sizeof(TLDFormatInfo));
253 TBuf8<sizeof(TVolFormatParam)> paramBuf;
256 if(fmtMode & ESpecialFormat)
258 //-- the user has provided format parameters structure.
259 //-- IPC argument #2 contains a structure: <TUint32>[optional package descriptor]
260 //-- 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
261 const TInt desLen = aRequest->GetDesLength(KMsgPtr2);
262 ASSERT((TUint32)desLen >= sizeof(TUint32));
264 const TInt dataPckgLen = desLen - sizeof(TUint32);
266 if((TUint32)dataPckgLen > sizeof(TUint32))
268 aRequest->ReadL(KMsgPtr2, paramBuf);
271 if(dataPckgLen == sizeof(TLDFormatInfo))
272 {//-- the user has provided formatting parameters via TLDFormatInfo structure.
273 pLDFormatInfo = (const TLDFormatInfo*)(paramBuf.Ptr() + sizeof(TUint32));
275 else if(dataPckgLen == sizeof(TVolFormatParam))
276 {//-- it's likely to be TVolFormatParam, need to check UId to be sure.
277 pVolFormatParam = (const TVolFormatParam*)(const TVolFormatParam*)(paramBuf.Ptr() + sizeof(TUint32));
279 if(pVolFormatParam->iUId == TVolFormatParam::KUId) //-- check the class UID
280 {//-- this is the real TVolFormatParam object passed
281 newFsNameHash = pVolFormatParam->FSNameHash();
284 else if(dataPckgLen >0)
285 {//-- parameters data structure has strange length
291 //-------------------
292 if(!newFsNameHash && currFsNameHash)
293 {//-- new file system name isn't specified (default formatting), but the volume had been forcedly dismounted.
294 //-- restore the original file system
295 newFsNameHash = currFsNameHash;
299 {//-- check if the specified FS is already mounted on the volume
302 drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
305 { //-- the iCurrentMount can be NULL, use the iFsys - the real file system associated with this drive
306 buf = drive.GetFSys()->Name();
309 const TUint32 currFSNameHash = TVolFormatParam::CalcFSNameHash(buf);
310 if(currFSNameHash == newFsNameHash)
311 {//-- no need to do anything, the required FS is already mounted
318 //-- the user has specified some filesystem to be mounted on the volume. Check if this FS is supported at all.
319 //-- if it is supported, but some other FS is currently mounted, it will be dismounted and the new one will be forced.
322 for(TInt cntFS=0; ;++cntFS)
324 nRes = drive.FSys().GetSupportedFileSystemName(cntFS, buf); //-- enumerate possible child file systems
327 return KErrNotSupported; //-- the filesystem with the given name (fsNameHash) is not supported.
329 if(newFsNameHash == TVolFormatParam::CalcFSNameHash(buf))
330 {//-- the filesystem with the given name (fsNameHash) is supported, but some other filesystem can be already mounted
332 bNeedForceMount = ETrue; //-- this will force the desired FS to be mounted
340 //-- try force mounting the desired file system if it is required
343 const TInt KMaxRetries = 3;
344 for(TInt cnt=0; ; ++cnt)
346 drive.MountFileSystem(ETrue, newFsNameHash);
348 nMountRes = drive.GetReason();
349 if(nMountRes == KErrNone || nMountRes == KErrLocked)
352 drive.Dismount(); //-- will reset mount retries counter
354 if(cnt >= KMaxRetries)
356 __PRINT1(_L("FsFormatOpen() can't mount FS! res:%d"), nMountRes);
362 ASSERT(nMountRes == KErrNone || nMountRes == KErrLocked);
364 __ASSERT_DEBUG(drive.CurrentMount().LockStatus()==0, Fault(ESvrFormatOpenFailed));
368 drive.DriveInfo(dInfo);
369 const TInt mediaAtt = dInfo.iMediaAtt;
371 #if defined(_LOCKABLE_MEDIA)
372 if (!(fmtMode & EForceErase) && (mediaAtt & KMediaAttLocked))
374 // if attempting to format a locked drive, dismount otherwise subsequent
375 // requests will operate on a mount that has been forcibly mounted (a few lines above)
376 CMountCB* pM = &drive.CurrentMount();
381 drive.MountFileSystem(EFalse); // clear iCurrentMount
386 if (!(mediaAtt & KMediaAttFormattable) || (mediaAtt & KMediaAttWriteProtected))
388 CMountCB* pM = &drive.CurrentMount();
393 drive.MountFileSystem(EFalse);
394 return KErrAccessDenied;
397 //-- instantinate and open CFormatCB object for this drive
398 CFormatCB* formatCB=NULL;
401 TRAPD(ret, formatCB = drive.FormatOpenL(aRequest, fmtHandle, fmtMode, pLDFormatInfo, pVolFormatParam ));
411 TPtrC8 pH((TUint8*)&fmtHandle,sizeof(TInt));
412 aRequest->WriteL(KMsgPtr3,pH);
415 TPtrC8 pCount((TUint8*)&count,sizeof(TInt));
416 aRequest->WriteL(KMsgPtr2,pCount);
417 aRequest->Session()->IncResourceCount();
422 TInt TFsFormatOpen::DoRequestL(CFsRequest* aRequest)
424 // Open a drive for formatting.
427 // Can not format if any files are clamped
428 TInt r=FsFormatOpen(aRequest);
432 TInt TFsFormatOpen::Initialise(CFsRequest* aRequest)
438 if (!KCapFsFormatOpen.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Format Open")))
439 return KErrPermissionDenied;
440 r=ParseNoWildSubstPtr0(aRequest,aRequest->Src());
443 if (aRequest->Src().NameOrExtPresent())
445 if (aRequest->SubstedDrive())
446 return(KErrAccessDenied);
451 TInt TFsFormatNext::DoRequestL(CFsRequest* aRequest)
453 // Format the next part of the media.
457 __PRINT1(_L("TFsFormatNext::DoRequestL() drv:%d"), aRequest->DriveNumber());
458 CFormatCB* format=(CFormatCB*)aRequest->ScratchValue();
459 TInt r=format->CheckMount();
460 if (r!=KErrNone && r!=KErrInUse)
462 __PRINT1(_L("TFsFormatNext::DoRequestL() err:%d"), r);
466 TPtr8 pStep((TUint8*)&format->CurrentStep(),sizeof(TInt));
467 aRequest->ReadL(KMsgPtr0,pStep);
469 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFormatCBDoFormatStepL, EF32TraceUidFileSys, format);
470 TRAP(r,format->DoFormatStepL());
471 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFormatCBDoFormatStepLRet, EF32TraceUidFileSys, r, format->CurrentStep());
474 aRequest->WriteL(KMsgPtr0,pStep);
475 if (r==KErrNone && format->CurrentStep()==0)
477 FsNotify::DiskChange(aRequest->DriveNumber());
482 TInt TFsFormatNext::Initialise(CFsRequest* aRequest)
487 if (!KCapFsFormatNext.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Format Next")))
488 return KErrPermissionDenied;
490 format=GetFormatFromHandle(aRequest->Message().Int3(), aRequest->Session());
492 return(KErrBadHandle);
493 aRequest->SetDrive(&format->Drive());
494 aRequest->SetScratchValue((TUint)format);