os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_fmt.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     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 	}