userlibandfileserver/fileserver/sfile/sf_fmt.cpp
changeset 0 a41df078684a
child 134 95847726fe57
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfile\sf_fmt.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "sf_std.h"
       
    19 
       
    20 LOCAL_C CFormatCB* GetFormatFromHandle(TInt aHandle,CSessionFs* aSession)
       
    21 //
       
    22 // Get the format control block from aHandle
       
    23 //
       
    24 	{
       
    25 	return((CFormatCB*)(SessionObjectFromHandle(aHandle,Formats->UniqueID(),aSession)));
       
    26 	}
       
    27 
       
    28 
       
    29 
       
    30 /**
       
    31 Default constructor.
       
    32 */
       
    33 EXPORT_C CFormatCB::CFormatCB()
       
    34 	{
       
    35 	}
       
    36 
       
    37 
       
    38 
       
    39 
       
    40 /**
       
    41     Destructor.
       
    42     Frees resources before destruction of the object.
       
    43 */
       
    44 EXPORT_C CFormatCB::~CFormatCB()
       
    45 	{
       
    46 
       
    47 	if (iMount)
       
    48 		{
       
    49 		RemoveDiskAccess(*iMount);
       
    50 		iMount->Drive().SetChanged(ETrue);
       
    51 		iMount->Close();
       
    52 		}
       
    53 	}
       
    54 
       
    55 
       
    56 
       
    57 
       
    58 /**
       
    59     Checks that the disk media is still mounted.
       
    60     @return KErrNone if the media is still mounted; KErrDisMounted otherwise.
       
    61 */
       
    62 EXPORT_C TInt CFormatCB::CheckMount()
       
    63 	{
       
    64 
       
    65 	TDrive& d=Drive();
       
    66 	TInt r=d.CheckMount();
       
    67 	if (r!=KErrNone)
       
    68 		return(r);
       
    69 	if (&Mount()!=&d.CurrentMount())
       
    70 		return(KErrDisMounted);
       
    71 	return(KErrNone);
       
    72 	}
       
    73 
       
    74 void CFormatCB::InitL(TDrive* aDrive,TFormatMode aMode)
       
    75 	{
       
    76 	DoInitL(aDrive->DriveNumber());
       
    77 	iDrive=aDrive;
       
    78 	iMount=&iDrive->CurrentMount();
       
    79 	iMode=aMode;
       
    80 	User::LeaveIfError(iMount->Open());
       
    81 	}
       
    82 
       
    83 
       
    84 EXPORT_C TInt CFormatCB::GetInterface(TInt /*aInterfaceId*/,TAny*& /*aInterface*/,TAny* /*aInput*/)
       
    85 	{
       
    86 	return(KErrNotSupported);
       
    87 	}
       
    88 
       
    89 
       
    90 //----------------------------------------------------------------------------
       
    91 /** 
       
    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
       
    94 */
       
    95 void CFormatCB::SetFormatParameters(const TLDFormatInfo* apLDFormatInfo)
       
    96     {
       
    97     TLDFormatInfo& fmtInfo = iSpecialInfo();
       
    98 
       
    99     if(!apLDFormatInfo)
       
   100         {//-- special meaning; invalidate iSpecialInfo by setting its package size as 0
       
   101         iSpecialInfo.SetLength(0);
       
   102         }
       
   103     else
       
   104         {
       
   105         Mem::Copy(&fmtInfo, apLDFormatInfo, sizeof(TLDFormatInfo));
       
   106         }
       
   107     }
       
   108 
       
   109 //----------------------------------------------------------------------------
       
   110 /** set volume formatting parameters, which are provided in TVolFormatParam structure */
       
   111 TInt CFormatCB::SetFormatParameters(const TVolFormatParam* apVolFormatParam)
       
   112     {
       
   113     ASSERT(apVolFormatParam);
       
   114     TAny* dummy;
       
   115     //-- push parameters to the particular implementation of the CFormatCB. Default behaviour: KErrNotSupported
       
   116     return GetInterface(ESetFmtParameters, dummy, (TAny*)apVolFormatParam);
       
   117     }
       
   118 
       
   119 //----------------------------------------------------------------------------
       
   120 #ifdef _DEBUG
       
   121 #define DUMP_OPENED_OBJECTS
       
   122 #endif
       
   123 
       
   124 /**
       
   125     Debug helper method. Dumps names of opened files and directories on this drive
       
   126     define DUMP_OPENED_OBJECTS to have it called
       
   127 */
       
   128 #ifdef DUMP_OPENED_OBJECTS
       
   129 static void DumpOpenedObjects(TDrive& aDrive)
       
   130     {
       
   131         {//-- 1. files 
       
   132         const TInt nFiles = Files->Count();
       
   133         for(TInt i=0; i<nFiles; ++i)
       
   134             {
       
   135             CFileCB* pFile=(CFileCB*)(*Files)[i];
       
   136             if(pFile->Drive().DriveNumber() == aDrive.DriveNumber())
       
   137                 {
       
   138                 __PRINT1(_L("FsFormatOpen() opened file:'%S'"), &pFile->FileName());
       
   139                 }
       
   140             }
       
   141         
       
   142         }
       
   143 
       
   144         {//-- 2. directories; CDirCB doesn't have associated name.
       
   145         const TInt nDirs = Dirs->Count();
       
   146         TInt cntDirs = 0;
       
   147         for(TInt i=0; i<nDirs; ++i)
       
   148             {
       
   149             CDirCB* pDir = (CDirCB*)(*Dirs)[i];
       
   150             if(pDir->Drive().DriveNumber() == aDrive.DriveNumber())
       
   151                 {
       
   152                 ++cntDirs;
       
   153                 }
       
   154             }
       
   155             
       
   156         if(cntDirs)
       
   157             {
       
   158             __PRINT1(_L("FsFormatOpen() opened directories:%d"), cntDirs);
       
   159             }
       
   160 
       
   161         }
       
   162 
       
   163     }
       
   164 #endif //DUMP_OPENED_OBJECTS
       
   165 
       
   166 //----------------------------------------------------------------------------
       
   167 /**
       
   168     Open a drive for formatting.
       
   169 */
       
   170 TInt FsFormatOpen(CFsRequest* aRequest)
       
   171 	{
       
   172     TDrive& drive = *aRequest->Drive();
       
   173 
       
   174 	__PRINT1(_L("FsFormatOpen() drv:%d"), drive.DriveNumber());
       
   175     
       
   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) 
       
   180         {
       
   181         __PRINT1(_L("FsFormatOpen() ChkMount:%d"), nMountRes);
       
   182         return nMountRes;
       
   183         }
       
   184     
       
   185     const TFormatMode fmtMode = (TFormatMode)aRequest->Message().Int1();
       
   186     TName buf;
       
   187     TUint32 currFsNameHash = 0; //-- current file system name hash, 0 means "not set"; used during forced FS dismounting
       
   188 
       
   189     if((nMountRes == KErrNone) && drive.CurrentMount().LockStatus() < 0)
       
   190         {//-- the mount is locked, it has normal objects (files, directories) opened on it. 
       
   191         
       
   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
       
   196 
       
   197 
       
   198         if(!(fmtMode & EForceFormat))
       
   199             {
       
   200             __PRINT(_L("FsFormatOpen() The mount is in use"));
       
   201             return KErrInUse;
       
   202             }    
       
   203 
       
   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!"));
       
   206 
       
   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);
       
   210 
       
   211         //-- kill the current mount
       
   212         FsThreadManager::LockDrive(drive.DriveNumber());
       
   213         TInt nRes = drive.ForceUnmountFileSystemForFormatting();
       
   214         FsThreadManager::UnlockDrive(drive.DriveNumber());
       
   215 
       
   216         
       
   217         switch(nRes)
       
   218             {
       
   219             case KErrInUse: 
       
   220             __PRINT(_L("FsFormatOpen() The mount has clamps! Can't force dismount"));    
       
   221             return KErrInUse; //-- there are clamps on this drive - can't dismount
       
   222 
       
   223             case KErrNone:
       
   224             break;
       
   225 
       
   226             default:
       
   227             ASSERT(0); //-- unexpected error code
       
   228             return nRes;
       
   229 
       
   230             };
       
   231 
       
   232         if(fmtMode & EQuickFormat)
       
   233             {//-- quick format may require the normally mounted FS, make the best effrot to mount it
       
   234             nMountRes = drive.CheckMount();
       
   235             }
       
   236         else
       
   237             {//-- this will make the FS mounted by force; for full format it will be quicker
       
   238             nMountRes = KErrCorrupt;
       
   239             }
       
   240 
       
   241         }
       
   242 
       
   243 	//-- if True, we will need mount (probably specific) file system by force because normal mounting has failed
       
   244     TBool bNeedForceMount = (nMountRes != KErrNone); 
       
   245 
       
   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"
       
   248 
       
   249     const TLDFormatInfo*    pLDFormatInfo   = NULL;
       
   250     const TVolFormatParam*  pVolFormatParam = NULL;
       
   251 
       
   252     __ASSERT_COMPILE(sizeof(TVolFormatParam) >= sizeof(TLDFormatInfo));
       
   253     TBuf8<sizeof(TVolFormatParam)> paramBuf;
       
   254    
       
   255     
       
   256     if(fmtMode & ESpecialFormat)  
       
   257         {   
       
   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));
       
   263     
       
   264         const TInt dataPckgLen = desLen - sizeof(TUint32);
       
   265 
       
   266         if((TUint32)dataPckgLen > sizeof(TUint32))
       
   267             {
       
   268             aRequest->ReadL(KMsgPtr2, paramBuf); 
       
   269             }
       
   270         
       
   271         if(dataPckgLen == sizeof(TLDFormatInfo))
       
   272             {//-- the user has provided formatting parameters via TLDFormatInfo structure.
       
   273             pLDFormatInfo = (const TLDFormatInfo*)(paramBuf.Ptr() + sizeof(TUint32));
       
   274             }
       
   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));
       
   278 
       
   279             if(pVolFormatParam->iUId == TVolFormatParam::KUId)  //-- check the class UID
       
   280                 {//-- this is the real TVolFormatParam object passed
       
   281                 newFsNameHash = pVolFormatParam->FSNameHash();
       
   282                 }
       
   283             }
       
   284         else if(dataPckgLen >0)
       
   285             {//-- parameters data structure has strange length
       
   286             return KErrArgument;
       
   287             }
       
   288     
       
   289         }
       
   290 
       
   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;
       
   296         }
       
   297     
       
   298     if(newFsNameHash)
       
   299         {//-- check if the specified FS is already mounted on the volume
       
   300         if(!bNeedForceMount)
       
   301             {
       
   302             drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
       
   303             }
       
   304         else
       
   305             { //-- the iCurrentMount can be NULL, use the iFsys - the real file system associated with this drive
       
   306             buf = drive.GetFSys()->Name();
       
   307             }
       
   308 
       
   309         const TUint32 currFSNameHash = TVolFormatParam::CalcFSNameHash(buf);
       
   310         if(currFSNameHash == newFsNameHash)
       
   311             {//-- no need to do anything, the required FS is already mounted
       
   312             newFsNameHash = 0; 
       
   313             } 
       
   314         }
       
   315 
       
   316     if(newFsNameHash) 
       
   317         {
       
   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.
       
   320         TInt nRes;
       
   321             
       
   322         for(TInt cntFS=0; ;++cntFS)
       
   323             {
       
   324             nRes = drive.FSys().GetSupportedFileSystemName(cntFS, buf); //-- enumerate possible child file systems
       
   325             
       
   326             if(nRes != KErrNone)
       
   327                 return KErrNotSupported; //-- the filesystem with the given name (fsNameHash) is not supported.
       
   328 
       
   329             if(newFsNameHash == TVolFormatParam::CalcFSNameHash(buf))
       
   330                 {//-- the filesystem with the given name (fsNameHash) is supported, but some other filesystem can be already mounted
       
   331                 drive.Dismount();
       
   332                 bNeedForceMount = ETrue; //-- this will force the desired FS to be mounted
       
   333                 break;
       
   334                 }
       
   335             }
       
   336     
       
   337         }//if(fsNameHash) 
       
   338 
       
   339 
       
   340     //-- try force mounting the desired file system if it is required
       
   341     if(bNeedForceMount)
       
   342         {
       
   343         const TInt KMaxRetries = 3;
       
   344         for(TInt cnt=0; ; ++cnt)
       
   345             {
       
   346             drive.MountFileSystem(ETrue, newFsNameHash);
       
   347 
       
   348             nMountRes = drive.GetReason();
       
   349             if(nMountRes == KErrNone || nMountRes == KErrLocked)
       
   350                 break;
       
   351             
       
   352             drive.Dismount(); //-- will reset mount retries counter
       
   353             
       
   354             if(cnt >= KMaxRetries)
       
   355                 {
       
   356                 __PRINT1(_L("FsFormatOpen() can't mount FS! res:%d"), nMountRes);    
       
   357                 return nMountRes;
       
   358                 }
       
   359             }
       
   360         }
       
   361 
       
   362     ASSERT(nMountRes == KErrNone || nMountRes == KErrLocked);
       
   363     
       
   364     __ASSERT_DEBUG(drive.CurrentMount().LockStatus()==0, Fault(ESvrFormatOpenFailed));
       
   365 
       
   366 
       
   367 	TDriveInfo dInfo;
       
   368 	drive.DriveInfo(dInfo);
       
   369 	const TInt mediaAtt = dInfo.iMediaAtt;
       
   370 
       
   371 #if defined(_LOCKABLE_MEDIA)
       
   372 	if (!(fmtMode & EForceErase) && (mediaAtt & KMediaAttLocked))
       
   373 		{
       
   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();
       
   377 		
       
   378         if(pM)
       
   379 			pM->Close();
       
   380 
       
   381 		drive.MountFileSystem(EFalse);	// clear iCurrentMount
       
   382 		return KErrLocked;
       
   383 		}
       
   384 #endif
       
   385 
       
   386 	if (!(mediaAtt & KMediaAttFormattable) || (mediaAtt & KMediaAttWriteProtected))
       
   387 		{
       
   388 		CMountCB* pM = &drive.CurrentMount();
       
   389 		
       
   390         if(pM)
       
   391 			pM->Close();
       
   392 
       
   393 		drive.MountFileSystem(EFalse);
       
   394         return KErrAccessDenied;
       
   395 		}
       
   396 
       
   397 	//-- instantinate and open CFormatCB object for this drive
       
   398     CFormatCB* formatCB=NULL;
       
   399 	TInt fmtHandle;
       
   400     
       
   401     TRAPD(ret, formatCB = drive.FormatOpenL(aRequest, fmtHandle, fmtMode, pLDFormatInfo, pVolFormatParam ));
       
   402 
       
   403 	if (ret!=KErrNone)
       
   404 		{
       
   405 		if(formatCB)
       
   406 			formatCB->Close();
       
   407 
       
   408 		return ret;
       
   409 		}
       
   410 
       
   411 	TPtrC8 pH((TUint8*)&fmtHandle,sizeof(TInt));
       
   412 	aRequest->WriteL(KMsgPtr3,pH);
       
   413 	TInt count=100;
       
   414 
       
   415 	TPtrC8 pCount((TUint8*)&count,sizeof(TInt));
       
   416 	aRequest->WriteL(KMsgPtr2,pCount);
       
   417 	aRequest->Session()->IncResourceCount();
       
   418 	
       
   419     return KErrNone;
       
   420 	}
       
   421 
       
   422 TInt TFsFormatOpen::DoRequestL(CFsRequest* aRequest)
       
   423 //
       
   424 // Open a drive for formatting.
       
   425 //
       
   426 	{
       
   427 	// Can not format if any files are clamped
       
   428 	TInt r=FsFormatOpen(aRequest);
       
   429 	return r;
       
   430 	}
       
   431 
       
   432 TInt TFsFormatOpen::Initialise(CFsRequest* aRequest)
       
   433 //
       
   434 //
       
   435 //
       
   436 	{
       
   437 	TInt r;
       
   438 	if (!KCapFsFormatOpen.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Format Open")))
       
   439 		return KErrPermissionDenied;
       
   440 	r=ParseNoWildSubstPtr0(aRequest,aRequest->Src());
       
   441 	if (r!=KErrNone)
       
   442 		return(r);
       
   443 	if (aRequest->Src().NameOrExtPresent())
       
   444 		return(KErrBadName);
       
   445 	if (aRequest->SubstedDrive())
       
   446 		return(KErrAccessDenied);
       
   447 	return(r);
       
   448 	}
       
   449 
       
   450 
       
   451 TInt TFsFormatNext::DoRequestL(CFsRequest* aRequest)
       
   452 //
       
   453 // Format the next part of the media.
       
   454 //
       
   455 	{
       
   456 
       
   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)
       
   461         {
       
   462     	__PRINT1(_L("TFsFormatNext::DoRequestL() err:%d"), r);
       
   463         return r;
       
   464         }
       
   465 
       
   466 	TPtr8 pStep((TUint8*)&format->CurrentStep(),sizeof(TInt));
       
   467 	aRequest->ReadL(KMsgPtr0,pStep);
       
   468 
       
   469 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFormatCBDoFormatStepL, EF32TraceUidFileSys, format);
       
   470 	TRAP(r,format->DoFormatStepL());
       
   471 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFormatCBDoFormatStepLRet, EF32TraceUidFileSys, r, format->CurrentStep());
       
   472 
       
   473 	if (r==KErrNone)
       
   474 		aRequest->WriteL(KMsgPtr0,pStep);
       
   475 	if (r==KErrNone && format->CurrentStep()==0)
       
   476 		{
       
   477 		FsNotify::DiskChange(aRequest->DriveNumber());
       
   478 		}
       
   479 	return(r);
       
   480 	}
       
   481 
       
   482 TInt TFsFormatNext::Initialise(CFsRequest* aRequest)
       
   483 //
       
   484 //
       
   485 //
       
   486 	{
       
   487 	if (!KCapFsFormatNext.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Format Next")))
       
   488 		return KErrPermissionDenied;
       
   489 	CFormatCB* format;
       
   490 	format=GetFormatFromHandle(aRequest->Message().Int3(), aRequest->Session());
       
   491 	if(!format)
       
   492 		return(KErrBadHandle);	
       
   493 	aRequest->SetDrive(&format->Drive());
       
   494 	aRequest->SetScratchValue((TUint)format);
       
   495 	return KErrNone;
       
   496 	}