os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_drv.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_drv.cpp
    15 // 
    16 //
    17 
    18 #include "sf_std.h"
    19 #include "sf_file_cache.h"
    20 
    21 
    22 //const TInt KMaxNotifierAttempts=4; // not used anywhere
    23 
    24 static TPtrC StripBackSlash(const TDesC& aName)
    25 //
    26 // If aName ends in a backslash, strip it.
    27 //
    28 	{
    29 
    30 	__ASSERT_DEBUG(aName.Length(),Fault(EStripBackSlashBadName));
    31 	if (aName[aName.Length()-1]==KPathDelimiter)
    32 		return(aName.Left(aName.Length()-1));
    33 	return(aName);
    34 	}
    35 
    36 static void CheckSubClose(CFsObject* anObj,TInt aHandle, CSessionFs* aSession)
    37 //
    38 // Close anObj if its not NULL.
    39 //
    40 	{
    41 	__PRINT1(_L("CheckSubClose() session 0x0%x"),aSession);
    42 	__PRINT1(_L("CheckSubClose() anObj 0x0%x"),anObj);
    43 
    44 	if(!anObj)
    45 		return;
    46 
    47 	if(aHandle==0)
    48 		{
    49 		// can't have been added to the object index
    50 		__ASSERT_DEBUG(KErrNotFound==aSession->Handles().At(anObj,ETrue),Fault(ESubOpenBadHandle));
    51 		anObj->Close();
    52 		}
    53 	else
    54 		aSession->Handles().Remove(aHandle,ETrue);
    55 	}
    56 
    57 TInt ValidateDrive(TInt aDriveNumber,CFsRequest* aRequest)
    58 //
    59 // Validate a drive number and set iTheDrive.
    60 //
    61 	{
    62 	if (aDriveNumber==KDefaultDrive)
    63 		aDriveNumber=aRequest->Session()->CurrentDrive();
    64 	if (!RFs::IsValidDrive(aDriveNumber))
    65 		return(KErrBadName);
    66 	aRequest->SetDrive(&TheDrives[aDriveNumber]);
    67 	return(KErrNone);
    68 	}
    69 
    70 TInt ValidateDriveDoSubst(TInt aDriveNumber,CFsRequest* aRequest)
    71 //
    72 // Validate a drive number and set iTheDrive.
    73 //
    74 	{
    75 
    76 	TInt r=ValidateDrive(aDriveNumber,aRequest);
    77 	if (r!=KErrNone)
    78 		return(r);
    79 	if (aRequest->Drive()->IsSubsted())
    80 		{
    81 		aRequest->SetSubstedDrive(aRequest->Drive());
    82 		aRequest->SetDrive(&aRequest->Drive()->SubstedDrive());
    83 		}
    84 	return(KErrNone);
    85 	}
    86 
    87 void ValidateAtts(TUint /*anEntryAtts*/,TUint& aSetAttMask,TUint& aClearAttMask)
    88 //
    89 // Do not allow the entry type to be changed
    90 //
    91 	{
    92 	const TUint KReadOnlySetAtts = KEntryAttVolume | 
    93 								   KEntryAttDir    | 
    94 								   KEntryAttRemote;
    95 
    96 	const TUint KReadOnlyClrAtts = KEntryAttVolume | 
    97 								   KEntryAttDir    | 
    98 								   KEntryAttRemote | 
    99 								   KEntryAttModified;
   100 
   101 	aSetAttMask   &= ~KReadOnlySetAtts;
   102 	aClearAttMask &= ~KReadOnlyClrAtts;
   103 	}
   104 
   105 void CheckForLeaveAfterOpenL(TInt leaveError, CFsRequest* aRequest, TInt aHandle)
   106 //
   107 // Tidy up in the event of a leave after opening a file or directory
   108 	{
   109 	if (leaveError)
   110 		{
   111 		CFsObject* anObj=(CFsObject* )aRequest->ScratchValue();
   112 		CheckSubClose(anObj,aHandle,aRequest->Session());
   113 		User::Leave(leaveError);
   114 		}
   115 	}
   116 
   117 TDrive::TDrive()
   118 //
   119 // Constructor.
   120 //
   121 	: iDriveNumber(0),iAtt(0),iChanged(EFalse),
   122 	  iFSys(NULL),iCurrentMount(NULL),iSubstedDrive(NULL),iSubst(NULL),
   123 	  iMount(NULL),iDriveFlags(0),iMountFailures(0)
   124 	{}
   125 
   126 void TDrive::CreateL(TInt aDriveNumber)
   127 //
   128 // Allocate the drive number and any resources.
   129 //
   130 	{
   131 	__PRINT1(_L("TDrive::CreateL(%d)"),aDriveNumber);
   132 	iDriveNumber=aDriveNumber;
   133 	iMount=TheContainer->CreateL();
   134 	TInt r=iLock.CreateLocal();
   135 	User::LeaveIfError(r);
   136 	}
   137 
   138 TInt TDrive::CheckMountAndEntryName(const TDesC& aName)
   139 //
   140 // Check drive is mounted then check aName is legal
   141 //
   142 	{
   143 
   144 	__PRINT1(_L("TDrive::CheckMountAndEntryName Drive%d"),DriveNumber());
   145 	TInt r=CheckMount();
   146 	if (r==KErrNone && IsIllegalFullName(aName))
   147 		return(KErrBadName);
   148 	return(r);
   149 	}
   150 
   151 void TDrive::MultiSlotDriveCheck()
   152 	{
   153 	// Check whether the current drive is a dual-slot/multi-slot
   154 	// if so, we need to check which drive is connected now and 
   155 	// swap the mapping in LocalDrives::iMapping such that the 
   156 	// mapping of driveNumber to localDriveNumber is correct.
   157 
   158 	Lock();
   159 	//Is this a multislot drive?
   160 	if(LocalDrives::iIsMultiSlotDrive[iDriveNumber])
   161 		{
   162 		for(TInt localDrvNum=0; localDrvNum<KMaxLocalDrives; localDrvNum++)
   163 			{
   164 			// ensure that this local drive is a multi-slot choice for this drive number..
   165 			if(LocalDrives::iReverseMapping[localDrvNum]==iDriveNumber)
   166 				{
   167 				// Caps - find out which one is connected
   168 				TLocalDriveCapsBuf capsInfo;
   169 				TInt r = LocalDrives::iLocalDrives[localDrvNum].Caps(capsInfo);
   170 				if(r==KErrNotReady)
   171 					{
   172 					continue; //go to next localdrive
   173 					}
   174 				//found a connected drive
   175 				//Update mapping
   176 				#ifdef _DEBUG
   177 				RDebug::Print(_L("Multislot drive mapping update: DriveNum %d to LocDrv %d"),iDriveNumber,localDrvNum);
   178 				#endif
   179 				
   180 				LocalDrives::iMapping[iDriveNumber] = localDrvNum;
   181 				break; // Swap complete - don't look any further
   182 				}
   183 			}
   184 		}	
   185 	UnLock();
   186 	}
   187 
   188 TInt TDrive::CheckMount()
   189 //
   190 // Check the drive and try to mount a media if not already mounted.
   191 //
   192 	{
   193 	__PRINT2(_L("TDrive::CheckMount Drive%d, changed:%d"),DriveNumber(), iChanged);
   194 	__CHECK_DRIVETHREAD(iDriveNumber);
   195 	
   196 	if (!iFSys)
   197 		return KErrNotReady;
   198 		
   199 	if (iChanged)				//	If a media change has occurred
   200 		{
   201 		iMountFailures = 0;
   202 		iChanged=EFalse;		//	Reset the flag
   203 		if (IsMounted())		//	Dismount the mount if it is still marked as mounted
   204 			{
   205             DoDismount();
   206 			}
   207 		//If we have a dual/multi removable media slot then we may need to
   208 		//swop the mappings.
   209 		MultiSlotDriveCheck();
   210 		}
   211 	
   212 	if (!IsMounted())				//	Checks that iCurrentMount!=NULL
   213 		{
   214 		__PRINT(_L("TDrive::CheckMount() Not Mounted"));
   215         const TInt KMaxMountFailures = 3;
   216 		// if we've repeatedly failed to mount, give up until a media change
   217 		if (iMountFailures >= KMaxMountFailures)
   218 			{
   219 			__PRINT1(_L("TDrive::CheckMount() retries exceeded, last Err:%d"), iLastMountError);
   220 			return iLastMountError;
   221 			}
   222 
   223 		if (!ReMount())	    //	Have we just remounted a mount we have previously encountered?
   224 			{			
   225 			MountFileSystem(EFalse);	//	If not, mount it for the first time now
   226 			}
   227 		else if(IsWriteProtected() && IsWriteableResource())
   228 			{
   229 			DoDismount();
   230 			return KErrAccessDenied;
   231 			}
   232 		}
   233 
   234 	if (iReason==KErrNone && CurrentMount().LockStatus() > 0)
   235 	    {
   236     	//-- this meand that the mount has drive access objetcs opened (RFormat or RRawDisk)
   237         __PRINT1(_L("TDrive::CheckMount() Mount is locked! LockStaus:%d"), CurrentMount().LockStatus());
   238         return KErrInUse;
   239 	    }	
   240 
   241 	__PRINT1(_L("TDrive::CheckMount returned %d "),iReason);
   242 		
   243 	return(iReason);
   244 	}
   245 
   246 //----------------------------------------------------------------------------
   247 /**
   248     Try and re-mount any of the pending media
   249     
   250     @return ETrue if the mount matching media found and been attached back (set as iCurrentMount)
   251 */
   252 TBool TDrive::ReMount()
   253 	{
   254 	const TInt mCount=Mount().Count();
   255     __PRINT1(_L("TDrive::ReMount() MountCnt:%d"), mCount);
   256 	
   257 	const TInt u=(Mount().UniqueID()<<16);
   258 	iReason=KErrNone;
   259 	
   260     //-- try every instance of CMountCB that is associated with this object of TDrive.
   261     //-- mounts are stored in the container of mCount elements.
   262     //-- if some CMountCB recognises the media it belongs, it means that "remount succeded"
   263     for(TInt i=0; i<mCount; i++)
   264 		{
   265 		CMountCB* pM=(CMountCB*)Mount().At(u|i);
   266 		
   267         if (ReMount(*pM))
   268 			return ETrue;
   269 		}
   270 
   271 	return EFalse;
   272 	}
   273 
   274 //----------------------------------------------------------------------------
   275 /**
   276     Try and re-mount the specified media.
   277 
   278     @return ETrue if remounting succeeded - i.e. the CMountCB instance that matches the media is found in the 
   279     mounts container (Mount()) and bound to the media.
   280 */
   281 TBool TDrive::ReMount(CMountCB& aMount)
   282 	{
   283 	__PRINT1(_L("TDrive::ReMount(0x%x)"), &aMount);
   284 	iReason=KErrNone;
   285 
   286 	if (!aMount.IsDismounted() && !aMount.ProxyDriveDismounted())
   287 		{
   288 		aMount.SetDrive(this);
   289 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReMount, EF32TraceUidFileSys, DriveNumber());
   290 		
   291         //-- actually, this is asking CMountCB to see if it belongs to the current media. 
   292         iReason = aMount.ReMount();
   293 
   294 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReMountRet, EF32TraceUidFileSys, iReason);
   295 		
   296         if (iReason == KErrNone)	//	ReMount succeeded
   297 			{
   298 			aMount.Open();
   299 			iCurrentMount = &aMount;
   300 			__PRINT1(_L("TDrive::ReMount for Mount:0x%x OK!"), &aMount);
   301 			return ETrue;
   302 			}
   303 
   304 		__PRINT2(_L("TDrive::ReMount for Mount:0x%x failed iReason=%d"),&aMount,iReason);
   305 		}
   306 	else
   307 		{
   308 		__PRINT1(_L("TDrive::ReMount() failed - Mount:0x%x is dismounted"), &aMount);
   309 		}
   310 
   311 	return EFalse;
   312 	}
   313 
   314 
   315 
   316 //----------------------------------------------------------------------------
   317 /**
   318     Mount the media on the drive. Optionally force a bad media to be mounted.
   319     
   320     @param  apMount     out: pointer to the produced CMountCB object; NULL if the CMountCB is not constructed
   321     @param  aForceMount if ETrue, the filesystem will be forcedly mounted on the drive, disregarding what it contains. 
   322     @param  aFsNameHash file system name hash; see TDrive::MountFileSystem()   
   323 */
   324 void TDrive::DoMountFileSystemL(CMountCB*& apMount, TBool aForceMount, TUint32 aFsNameHash)
   325 	{
   326 	CFileSystem* pMountsFs = NULL; //-- reference to the filesystem that will be producing CMountCB
   327     
   328     apMount = NULL;
   329 
   330     TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber());
   331    
   332     //-- construct a new CmountCB object.
   333     //-- on return pMountsFs will be the pointer to the factory object of CFileSystem that produced this mount
   334     apMount = FSys().NewMountExL(this, &pMountsFs, aForceMount, aFsNameHash);
   335 
   336 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, KErrNone, apMount);
   337 	__PRINT2(_L("TDrive::MountMediaL created mount:0x%x FileSys:0x%x"), apMount, pMountsFs);
   338 
   339     ASSERT(pMountsFs && apMount);
   340 
   341 	apMount->SetMountNumber(iMountNumber++);
   342     apMount->InitL(*this, pMountsFs);  //-- initialise Mount
   343     apMount->MountL(aForceMount);      //-- mount the file system  
   344 	Mount().AddL(apMount,EFalse);      //-- add mount object to the mounts container.  
   345 
   346 	iCurrentMount=apMount;
   347     }
   348 
   349 
   350 //----------------------------------------------------------------------------
   351 /*
   352 	Mount file system on the drive. 
   353 	@param  aForceMount if EFalse, will try to mount the file system normally, the file system implementation will decide if it can work on this drive or not.
   354                         if ETrue, will mount the file suystem by force, this is used mostly for formatting unrecognisable media.
   355 
   356     @param  aFsNameHash optional parameter. Can specify the concrete file system name (hash). It can be used to force mounting  some specific
   357                         file system. Default value '0' means "not specified / not used"
   358                                                               
   359 
   360     TDrive::iReason on return contains the operation result code.
   361 */
   362 void TDrive::MountFileSystem(TBool aForceMount, TUint32 aFsNameHash /*=0*/ )
   363 	{
   364 	__PRINT2(_L("TDrive::MountFileSystem aForceMount=%d, FSNameHash:0x%x"),aForceMount, aFsNameHash);
   365 	__CHECK_DRIVETHREAD(iDriveNumber);
   366 	
   367     iCurrentMount=NULL;
   368 	if(!iFSys)
   369 		{
   370 		iReason=KErrNotReady;
   371 		return;
   372 		}
   373 	
   374     CMountCB* pM=NULL;
   375     TRAP(iReason, DoMountFileSystemL(pM, aForceMount, aFsNameHash));
   376 	if (iReason == KErrNone)
   377 		{
   378 		iMountFailures = 0;
   379 		ASSERT(iCurrentMount);
   380         }
   381 	else
   382 		{
   383 		iLastMountError = iReason;
   384 		iMountFailures++;
   385 		__PRINT2(_L("TDrive::MountFileSystem 0x%x failed iReason=%d"),pM,iReason);
   386 		if(pM)
   387 			pM->Close();
   388 		
   389         ASSERT(!iCurrentMount);
   390         }
   391 	}
   392 
   393 
   394 //----------------------------------------------------------------------------
   395 /**
   396     Generic mount control method.
   397     @param  aLevel  specifies the operation to perfrom on the mount
   398     @param  aOption specific option for the given operation
   399     @param  aParam  pointer to generic parameter, its meaning depends on aLevel and aOption
   400 
   401     @return standard error code.
   402 */
   403 TInt TDrive::MountControl(TInt aLevel, TInt aOption, TAny* aParam)
   404     {
   405 	TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBMountControl, EF32TraceUidFileSys, DriveNumber(), aLevel, aOption, aParam);
   406     TInt r = CurrentMount().MountControl(aLevel, aOption, aParam);
   407 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBMountControlRet, EF32TraceUidFileSys, r);
   408 
   409 	return r;
   410     }
   411 
   412 //----------------------------------------------------------------------------
   413 /**
   414     Request aFreeSpaceRequired free bytes from the mount associated with this drive.
   415     The volume free space on for some filesystems can be changing (usually increasing) after it has been mounted.
   416     If the mount supports this functionality, it can block this call until certain number of free bytes encounted if its free
   417     space calculation activity hasn't finished yet.
   418 
   419     @param  aFreeSpaceRequired  required free space, bytes.
   420     
   421     @return KErrNone        on success and if there is at least aFreeSpaceRequired bytes on the volume
   422             KErrDiskFull    on success and if there is no aFreeSpaceRequired bytes on the volume
   423             system-wide error code otherwise
   424 */
   425 TInt TDrive::RequestFreeSpaceOnMount(TUint64 aFreeSpaceRequired)
   426     {
   427     TInt nRes;
   428 
   429     nRes = CheckMount();
   430     if(nRes != KErrNone)
   431         return nRes;
   432 
   433     //-- 1. Try mount-specific request first. If the mount is still performing free space calculations,
   434     //-- the caller will be suspended until aFreeSpaceRequired bytes is available or scanning process finishes
   435     {
   436         TUint64 freeSpaceReq = aFreeSpaceRequired;
   437 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFreeSpace, EF32TraceUidFileSys, DriveNumber());
   438         nRes = CurrentMount().RequestFreeSpace(freeSpaceReq);
   439 		TRACERET3(UTF::EBorder, UTraceModuleFileSys::ECMountCBFreeSpaceRet, EF32TraceUidFileSys, nRes, I64LOW(freeSpaceReq), I64HIGH(freeSpaceReq));
   440         if(nRes == KErrNone)
   441             {
   442             return (freeSpaceReq >= aFreeSpaceRequired) ? KErrNone : KErrDiskFull;
   443             }
   444     }
   445 
   446     //-- given Mount doesn't support this functionality, use legacy method
   447     TVolumeInfo volInfo;
   448     nRes = Volume(volInfo);
   449     if(nRes !=KErrNone)
   450         return nRes;
   451 
   452     return ((TUint64)volInfo.iFree >= aFreeSpaceRequired) ? KErrNone : KErrDiskFull;
   453     }
   454 
   455 //----------------------------------------------------------------------------
   456 /**
   457     Get size of the mounted volume. It can be less than physical volume size because FileSystem data may occupy some space.
   458     
   459     @param  aSize on success mounted volume size in bytes will be returned there
   460     @return KErrNone on success, standard error code otherwise
   461 */
   462 TInt TDrive::MountedVolumeSize(TUint64& aSize)
   463     {
   464     TInt nRes;
   465 
   466     nRes = CheckMount();
   467     if(nRes != KErrNone)
   468         return nRes;
   469 
   470     //-- 1. Try mount-specific request first. It won't block this call as CMountCB::VolumeL() can do if some background activity is going on the mount
   471 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeSize, EF32TraceUidFileSys, DriveNumber());
   472     nRes = CurrentMount().MountedVolumeSize(aSize);
   473 	TRACERET3(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeSize, EF32TraceUidFileSys, nRes, I64LOW(aSize), I64HIGH(aSize));
   474     if(nRes == KErrNone)
   475         return nRes;
   476 
   477     //-- given Mount doesn't support this functionality, use legacy method
   478     TVolumeInfo volInfo;
   479     nRes = Volume(volInfo);
   480     if(nRes == KErrNone)
   481         {
   482         aSize = volInfo.iSize;
   483         }
   484     
   485     return nRes;
   486     }
   487 
   488 //----------------------------------------------------------------------------
   489 /**
   490     Get _current_ amount of free space on the volume. Some mounts implementations can be updating the amount of free space
   491     in background. 
   492 
   493     @param  aFreeDiskSpace on success will contain a current amount of free space
   494     @return KErrNone on success, standard error code otherwise
   495 
   496 */
   497 TInt TDrive::FreeDiskSpace(TInt64& aFreeDiskSpace)
   498 	{
   499     TInt nRes;
   500 
   501     nRes = CheckMount();
   502     if(nRes != KErrNone)
   503         return nRes;
   504 
   505     //-- 1. Try mount-specific request first. It won't block this call as CMountCB::VolumeL() can do 
   506 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCurrentFreeSpace, EF32TraceUidFileSys, DriveNumber());
   507     nRes = CurrentMount().GetCurrentFreeSpaceAvailable(aFreeDiskSpace);
   508 	TRACERET3(UTF::EBorder, UTraceModuleFileSys::ECMountCBCurrentFreeSpaceRet, EF32TraceUidFileSys, nRes, I64LOW(aFreeDiskSpace), I64HIGH(aFreeDiskSpace));
   509     if(nRes == KErrNone)
   510         return nRes;
   511 
   512     //-- given Mount doesn't support this functionality, use legacy method
   513     TVolumeInfo volInfo;
   514     nRes = Volume(volInfo);
   515     if(nRes == KErrNone)
   516         {
   517         aFreeDiskSpace = volInfo.iFree;
   518         }
   519     
   520     return nRes;
   521 	}
   522 
   523 //----------------------------------------------------------------------------
   524 /**
   525     Finalise drive (the mount).
   526 
   527     @param  aOperation  describes finalisation operation ,see RFs::TFinaliseDrvMode
   528     @param  aParam1     not used, for future expansion
   529     @param  aParam2     not used, for future expansion
   530 
   531     @return Standard error code
   532 */
   533 TInt TDrive::FinaliseMount(TInt aOperation, TAny* aParam1/*=NULL*/, TAny* aParam2/*=NULL*/)
   534 	{
   535 	TInt r=CheckMount();
   536 	if (r!=KErrNone)
   537 		return(r);
   538 
   539 	r = FlushCachedFileInfo();
   540 	if (r!=KErrNone)
   541 		return(r);
   542 
   543 	if(IsWriteProtected())
   544 		return(KErrAccessDenied);
   545 
   546 	TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount2, EF32TraceUidFileSys, DriveNumber(), aOperation, aParam1, aParam2);
   547 	TRAP(r,CurrentMount().FinaliseMountL(aOperation, aParam1, aParam2));
   548 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount2Ret, EF32TraceUidFileSys, r);
   549 	
   550     return r;
   551 	}
   552 
   553 //----------------------------------------------------------------------------
   554 /** old implementation */
   555 TInt TDrive::FinaliseMount()
   556 	{
   557 	TInt r=CheckMount();
   558 	if (r!=KErrNone)
   559 		return(r);
   560 
   561 	r = FlushCachedFileInfo();
   562 	if (r!=KErrNone)
   563 		return(r);
   564 
   565 	if(IsWriteProtected())
   566 		return(KErrAccessDenied);
   567 
   568 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount1, EF32TraceUidFileSys, DriveNumber());
   569 	TRAP(r,CurrentMount().FinaliseMountL());
   570 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount1Ret, EF32TraceUidFileSys, r);
   571 	
   572     return r;
   573 	}
   574 
   575 
   576 
   577 CFileCB* TDrive::LocateFile(const TDesC& aName)
   578 //
   579 //	Locate a file of the same name already open on the drive.
   580 //
   581 	{
   582 	TDblQueIter<CFileCB> q(CurrentMount().iMountQ);
   583 	CFileCB* pF;
   584 	// early out for normal case, list is empty
   585 	if(q==NULL)
   586 		return NULL;
   587 	
   588 	// strip off trailing dots
   589 	TInt length= aName.Length();
   590 	while((length !=0) && (aName[length-1]==KExtDelimiter))
   591 		{
   592 		length--;
   593 		}
   594 
   595 	TPtrC temp(aName.Ptr(),length);
   596 
   597 	TFileName tempName;
   598 	tempName.CopyF(temp);
   599 	TUint32 nameHash=CalcNameHash(tempName);
   600 
   601 	while ((pF=q++)!=NULL)
   602 		{
   603 		if(nameHash==pF->NameHash())
   604 			{
   605 			if (pF->FileNameF().Match(tempName)==KErrNone)
   606 				return(pF);
   607 			}	
   608 		}
   609 	return(NULL);
   610 	}
   611 
   612 
   613 CFileCache* TDrive::LocateClosedFile(const TDesC& aName, TBool aResurrect)
   614 //
   615 //	Locate a recently closed file of the same name on the drive.
   616 //
   617 	{
   618 	// strip off trailing dots
   619 	TInt length= aName.Length();
   620 	while((length !=0) && (aName[length-1]==KExtDelimiter))
   621 		{
   622 		length--;
   623 		}
   624 
   625 	TPtrC temp(aName.Ptr(),length);
   626 
   627 	TFileName tempName;
   628 	tempName.CopyF(temp);
   629 	TUint32 nameHash=CalcNameHash(tempName);
   630 
   631 	CFileCache* pF = NULL;
   632 	CMountCB* currentMount = &CurrentMount();
   633 
   634 
   635 	TClosedFileUtils::Lock();
   636 
   637 	TInt count = TClosedFileUtils::Count();
   638 	while(count--)
   639 		{
   640 		CFileCache* fileCache = TClosedFileUtils::At(count);
   641 		if (&fileCache->Drive() == this &&
   642 			fileCache->NameHash()== nameHash && 
   643 			fileCache->FileNameF().Match(tempName)==KErrNone &&
   644 			&fileCache->Mount() == currentMount)
   645 			{
   646 			__ASSERT_DEBUG(TClosedFileUtils::IsClosed(fileCache), Fault(EObjRemoveContainerNotFound));
   647 			__CACHE_PRINT2(_L("CLOSEDFILES: LocateClosedFile(%S, %d\n"), &fileCache->FileNameF(), aResurrect);
   648 			if (aResurrect)
   649 				{
   650 				TClosedFileUtils::ReOpen(fileCache, EFalse);
   651 				}
   652 			pF = fileCache;
   653 			break;
   654 			}
   655 
   656 		}
   657 	TClosedFileUtils::Unlock();
   658 
   659 	if (pF != NULL && !aResurrect)
   660 		{
   661 		pF->Close();
   662 		pF = NULL;
   663 		}
   664 
   665 	return(pF);
   666 	}
   667 
   668 
   669 static TBool IsSubDir(const TDesC& aFullName,const TDesC& aParent)
   670 //
   671 // Returns ETrue if aFullName is a subdirectory of aParent
   672 // Assumes aParent is a path name with the trailing backslash removed
   673 //
   674 	{
   675 
   676 	__ASSERT_DEBUG(aParent.Length() && aParent[aParent.Length()-1]!=KPathDelimiter,Fault(EIsSubDirBadDes));
   677 	TPtrC entryFullName(NULL,0);
   678 	TPtrC entryParent(NULL,0);
   679 	TInt posFullName=0;
   680 	TInt posParent=0;
   681 
   682 	FOREVER
   683 		{
   684 		NextInPath(aParent,entryParent,posParent);
   685 		if (entryParent.Length()==0)
   686 			break;
   687 		NextInPath(aFullName,entryFullName,posFullName);
   688 		if (entryParent!=entryFullName)
   689 			return(EFalse);
   690 		}
   691 
   692 	if (aFullName.Length()<=posFullName)
   693 		return(EFalse);
   694 	if (aFullName[posFullName]!=KPathDelimiter)
   695 		return(EFalse);
   696 	return(ETrue);
   697 	}
   698 
   699 CFileCB* TDrive::LocateFileByPath(const TDesC& aPath)
   700 //
   701 // Locate a file opened in a subdirectory of aPath
   702 //
   703 	{
   704 
   705 	TDblQueIter<CFileCB> q(CurrentMount().iMountQ);
   706 	CFileCB* pF;
   707 	while ((pF=q++)!=NULL)
   708 		{
   709 		if (IsSubDir(pF->FileName(),aPath))
   710 			return(pF);
   711 		}
   712 	return(NULL);
   713 	}
   714 
   715 void TDrive::FlushCachedFileInfoL()
   716 //
   717 // Flush data stored in the file control blocks
   718 //
   719 	{
   720 	__CHECK_DRIVETHREAD(iDriveNumber);
   721 	TDblQueIter<CFileCB> q(CurrentMount().iMountQ);
   722 	CFileCB* pF;
   723 	while ((pF=q++)!=NULL)
   724 		{
   725 		if (pF->iAtt&KEntryAttModified)
   726 			pF->FlushAllL();
   727 		}
   728 	}
   729 
   730 /**
   731 Flushes (asynchronously) all dirty data on this drive and optionally
   732 purges non-dirty data
   733 
   734 aPurgeCache - purges all file caches on this drive AFTER dirty data has ben flushed 
   735 
   736 returns KErrNone if complete
   737 		CFsRequest::EReqActionBusy if flushing is in progress
   738 		otherwise one of the other system-wide error codes.
   739 */
   740 TInt TDrive::FlushCachedFileInfo(TBool aPurgeCache)
   741 	{
   742 	if (iCurrentMount == NULL)
   743 		return KErrNone;
   744 
   745 	TBool driveThread = FsThreadManager::IsDriveThread(iDriveNumber,EFalse);
   746 
   747 	Lock();
   748 	
   749 
   750 	TInt ret = KErrNone;
   751 
   752 	TDblQueIter<CFileCB> q(iCurrentMount->iMountQ);
   753 	CFileCB* pF;
   754 	while ((pF=q++)!=NULL)
   755 		{
   756 		CFileCache* fileCache = pF->FileCache();
   757 
   758 		// Write dirty data if there is a file cache
   759 		TInt flushDirtyRetCode = CFsRequest::EReqActionComplete;
   760 		if (fileCache)
   761 			{
   762 			flushDirtyRetCode = fileCache->FlushDirty();
   763 			if (flushDirtyRetCode == CFsRequest::EReqActionComplete)	// nothing to flush
   764 				{
   765 				if (aPurgeCache)
   766 					fileCache->Purge(EFalse);
   767 				}
   768 			else if (flushDirtyRetCode == CFsRequest::EReqActionBusy)	// flushing
   769 				{
   770 				ret = flushDirtyRetCode;
   771 				}
   772 			else	// error
   773 				{
   774 				ret = flushDirtyRetCode;
   775 				break;
   776 				}
   777 			}
   778 		// if no file cache or no dirty data left, update the file entry & attributes
   779 		if (driveThread && (pF->iAtt&KEntryAttModified) && flushDirtyRetCode == CFsRequest::EReqActionComplete )
   780 			{
   781 			TRAP(ret, pF->FlushAllL());
   782 			if (ret != KErrNone)
   783 				break;
   784 			}
   785 		}
   786 
   787 	UnLock();
   788 
   789 
   790 	return ret;
   791 	}
   792 
   793 //----------------------------------------------------------------------------
   794 /**
   795     Purge dirty cache data associated with all files on a given mount
   796 */
   797 void TDrive::PurgeDirty(CMountCB& aMount)
   798 	{
   799 	TDblQueIter<CFileCB> q(aMount.iMountQ);
   800 	CFileCB* pF;
   801 	while ((pF=q++)!=NULL)
   802 		{
   803 		CFileCache* fileCache = pF->FileCache();
   804 		if (fileCache)
   805 		    {
   806         	fileCache->Purge(ETrue);
   807             fileCache->MarkFileClean();
   808             }
   809 		}
   810 	}
   811 
   812 //----------------------------------------------------------------------------
   813 TInt TDrive::ValidateShare(CFileCB& aFile, TShare aReqShare)
   814 //
   815 // Check that the sharing rules are obeyed.
   816 //
   817 	{
   818 
   819 	switch (aReqShare)
   820 		{
   821 	case EFileShareExclusive:
   822 	case EFileShareReadersOnly:
   823 	case EFileShareAny:
   824 	case EFileShareReadersOrWriters:
   825 		break;
   826 	default:
   827 		return(KErrArgument);
   828 		}
   829 	switch (aFile.iShare)
   830 		{
   831 	case EFileShareExclusive:
   832 		return(KErrInUse);
   833 
   834 	case EFileShareReadersOnly:
   835 	case EFileShareAny:
   836 		if (aReqShare != aFile.iShare && aReqShare != EFileShareReadersOrWriters)
   837 			return(KErrInUse);
   838 		break;
   839 
   840 	case EFileShareReadersOrWriters:
   841 		if (aReqShare==EFileShareExclusive)
   842 			return(KErrInUse);
   843 		//
   844 		// If the file is currently open as EFileShareReadersOrWriters then
   845 		// promote the share to the requested share mode.
   846 		//
   847 		// If the requested share is EFileShareReadersOnly, verfiy that no
   848 		// other share has the file open for writing.
   849 		//
   850 
   851 		if (aReqShare == EFileShareReadersOnly)
   852 			{
   853 			FileShares->Lock();
   854 			TInt count = FileShares->Count();
   855 			while(count--)
   856 				{
   857 				CFileShare* share = (CFileShare*)(*FileShares)[count];
   858 				if (&share->File() == &aFile)
   859 					{
   860 					if(share->iMode & EFileWrite)
   861 						{
   862 						FileShares->Unlock();
   863 						return KErrInUse;
   864 						}
   865 					}
   866 				}
   867 			FileShares->Unlock();
   868 			}
   869 		break;
   870     
   871 	default:
   872 		Fault(EDrvIllegalShareValue);
   873         break;
   874 		}
   875 	return(KErrNone);
   876 	}
   877 
   878 void TDrive::DriveInfo(TDriveInfo& anInfo)
   879 //
   880 // Get the drive info.
   881 //
   882 	{
   883 	anInfo.iType=EMediaNotPresent;
   884 	anInfo.iMediaAtt=0;
   885 	anInfo.iBattery=EBatNotSupported;
   886     anInfo.iConnectionBusType=EConnectionBusInternal;
   887 
   888 	if(iFSys)
   889 		{
   890 		TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDriveInfo, EF32TraceUidFileSys, &FSys(), DriveNumber());
   891 		FSys().DriveInfo(anInfo,DriveNumber());
   892 		TRACE3(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDriveInfoRet, EF32TraceUidFileSys, 
   893 			anInfo.iType, anInfo.iDriveAtt, anInfo.iMediaAtt);
   894 		}
   895 
   896 	anInfo.iDriveAtt=Att();
   897 	}
   898 
   899 TInt TDrive::Volume(TVolumeInfo& aVolume)
   900 //
   901 // Get the drive volume info.
   902 //
   903 	{
   904 	TInt r=CheckMount();
   905 	if (r==KErrNone)
   906 		{
   907 		DriveInfo(aVolume.iDrive);
   908 		CMountCB& m=CurrentMount();
   909 		aVolume.iName=m.VolumeName();
   910 		aVolume.iUniqueID=m.iUniqueID;
   911 		aVolume.iSize=m.iSize;
   912 
   913 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeL, EF32TraceUidFileSys, DriveNumber());
   914 		TRAP(r,m.VolumeL(aVolume))
   915 		TRACE7(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeLRet, EF32TraceUidFileSys, 
   916 			r, aVolume.iUniqueID, I64LOW(aVolume.iSize), I64HIGH(aVolume.iSize),
   917 			I64LOW(aVolume.iFree), I64HIGH(aVolume.iFree), aVolume.iFileCacheFlags);
   918 
   919 		}
   920 	return(r);
   921 	}
   922 
   923 
   924 void TDrive::SetVolumeL(const TDesC& aName,HBufC*& aBuf)
   925 //
   926 // Set the volume name.
   927 //
   928 	{
   929 	__CHECK_DRIVETHREAD(iDriveNumber);
   930 	aBuf=aName.AllocL();
   931 	TPtr volumeName=aBuf->Des();
   932 
   933 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetVolumeL, EF32TraceUidFileSys, DriveNumber(), aName);
   934 	CurrentMount().SetVolumeL(volumeName);
   935 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetVolumeLRet, EF32TraceUidFileSys, KErrNone);
   936 
   937 
   938 	delete &CurrentMount().VolumeName();
   939 	CurrentMount().SetVolumeName(aBuf);
   940 	}
   941 
   942 TInt TDrive::SetVolume(const TDesC& aName)
   943 //
   944 // Set the volume name.
   945 //
   946 	{
   947 	TInt r=CheckMount();
   948 	HBufC* pV=NULL;
   949 	if (r==KErrNone)
   950 		{
   951 		if(IsWriteProtected())
   952 			return(KErrAccessDenied);
   953 		TRAP(r,SetVolumeL(aName,pV))
   954 		if (r!=KErrNone)
   955 			delete pV;
   956 		}
   957 	return(r);
   958 	}
   959 
   960 TInt TDrive::MkDir(const TDesC& aName)
   961 //
   962 // Make a directory.
   963 //
   964 	{
   965 	TInt r=CheckMount();
   966 	if (r!=KErrNone)
   967 		return(r);
   968 	if(IsWriteProtected())
   969 		return(KErrAccessDenied);
   970 	TParse newDirName;
   971 	newDirName.Set(aName,NULL,NULL);
   972 
   973 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBMkDirL, EF32TraceUidFileSys, DriveNumber(), aName);
   974 	TRAP(r,CurrentMount().MkDirL(newDirName.FullName()))
   975 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBMkDirLRet, EF32TraceUidFileSys, r);
   976 
   977 	return(r);
   978 	}
   979 
   980 TInt TDrive::RmDir(const TDesC& aName)
   981 //
   982 // Remove a directory.
   983 //
   984 	{
   985 	TInt r=CheckMount();
   986 	if (r!=KErrNone)
   987 		return(r);
   988 	TEntry entry;
   989 	r=Entry(aName,entry);
   990 	if (r!=KErrNone)
   991 		return(r);
   992 	if (entry.IsDir()==EFalse)
   993 		return(KErrPathNotFound);
   994 	if ((entry.iAtt&KEntryAttReadOnly) || IsWriteProtected())
   995 		return(KErrAccessDenied);
   996 
   997 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBRmDirL, EF32TraceUidFileSys, DriveNumber(), aName);
   998 	TRAP(r,CurrentMount().RmDirL(aName))
   999 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBRmDirLRet, EF32TraceUidFileSys, r);
  1000 
  1001 	return(r);
  1002 	}
  1003 
  1004 /*
  1005  Delete files allowing wild cards.
  1006 */
  1007 TInt TDrive::Delete(const TDesC& aName)
  1008 	{
  1009 	TInt r=CheckMountAndEntryName(aName);
  1010 	if(r!=KErrNone)
  1011 		return r;
  1012 	
  1013 	if(LocateFile(aName))
  1014 		return KErrInUse; //-- the file is already opened by someone
  1015 
  1016 	// remove from closed queue - NB this isn't strictly necessary if file is read-only or write-protected...
  1017 	LocateClosedFile(aName, EFalse);
  1018 
  1019     if (IsWriteProtected())
  1020 		return(KErrAccessDenied);
  1021 
  1022     //-- filesystems' CMountCB::DeleteL() implementations shall check the entry attributes themeselves. 
  1023 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteL, EF32TraceUidFileSys, DriveNumber(), aName);
  1024 	TRAP(r,CurrentMount().DeleteL(aName))
  1025 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteLRet, EF32TraceUidFileSys, r);
  1026 
  1027 	return r;
  1028 	}
  1029 
  1030 TInt TDrive::CheckMountAndEntryNames(const TDesC& anOldName,const TDesC& aNewName)
  1031 //
  1032 // Check mount, that neither is open, and that both names are legal.
  1033 //
  1034 	{
  1035 
  1036 	TInt r=CheckMountAndEntryName(anOldName);
  1037 	if (r!=KErrNone)
  1038 		return(r);
  1039 	if (IsIllegalFullName(aNewName))
  1040 		return(KErrBadName);
  1041 	return(KErrNone);
  1042 	}
  1043 
  1044 TInt TDrive::CheckDirectories(const TDesC& anOldName,const TDesC& aNewName)
  1045 //
  1046 // Return KErrAlreadyExists if aNewName exists and 
  1047 // KErrAccessDenied if anOldName is a directory being moved to a subdirectory of itself
  1048 //
  1049 	{
  1050 
  1051 	TEntry entry;
  1052 	TInt r=Entry(anOldName,entry);
  1053 	if (r!=KErrNone)
  1054 		return(r);
  1055 	if (entry.IsDir())
  1056 		{
  1057 	   	//-- check the length of the destination directory name. It shall not exceed 253 characters.
  1058         //-- aNewName looks like "\\dir1" i.e. drive letter and ':' is removed from the name and there is no trailing '\\' in this case. 
  1059 
  1060        	const TInt maxDirNameLength = KMaxFileName - 3;
  1061         if(aNewName.Length() > maxDirNameLength)
  1062             return KErrBadName;	
  1063 		if(IsSubDir(aNewName,anOldName))
  1064 			return(KErrInUse); // rename into a subdir of itself
  1065 		if (LocateFileByPath(anOldName))
  1066 			return(KErrInUse); // a file inside anOldName is open
  1067 		}
  1068 	else if (LocateFile(anOldName))
  1069 		return(KErrInUse);
  1070 	
  1071 	r=Entry(aNewName,entry);
  1072 	if (r!=KErrNone && r!=KErrNotFound)
  1073 		return(r);
  1074 	return(KErrNone);
  1075 	}
  1076 
  1077 TInt TDrive::Rename(const TDesC& anOldName,const TDesC& aNewName)
  1078 //
  1079 // Rename files or directories. No wild cards.
  1080 //
  1081 	{
  1082 	__CHECK_DRIVETHREAD(iDriveNumber);
  1083 	TInt r=CheckMountAndEntryNames(anOldName,aNewName);
  1084 	if (r!=KErrNone)
  1085 		return(r);
  1086 	TPtrC oldEntryName(StripBackSlash(anOldName));
  1087 	TPtrC newEntryName(StripBackSlash(aNewName));
  1088 	r=CheckDirectories(oldEntryName,newEntryName);
  1089 	if (r!=KErrNone)
  1090 		return(r);
  1091 	if(IsWriteProtected())
  1092 		return(KErrAccessDenied);
  1093 
  1094 	// remove from closed queue
  1095 	LocateClosedFile(anOldName, EFalse);
  1096 	LocateClosedFile(aNewName, EFalse);
  1097 
  1098 	TRACEMULT3(UTF::EBorder, UTraceModuleFileSys::ECMountCBRenameL, EF32TraceUidFileSys, DriveNumber(), oldEntryName,newEntryName);
  1099 	TRAP(r,CurrentMount().RenameL(oldEntryName,newEntryName))
  1100 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBRenameLRet, EF32TraceUidFileSys, r);
  1101 
  1102 	return(r);
  1103 	}
  1104 
  1105 TInt TDrive::Replace(const TDesC& anOldName,const TDesC& aNewName)
  1106 //
  1107 // Replace anOldName with aNewName atomically. No wild cards. No directories
  1108 //
  1109 	{
  1110 	TInt r=CheckMountAndEntryNames(anOldName,aNewName);
  1111 	if (r!=KErrNone)
  1112 		return(r);
  1113 	TEntry entry;
  1114 	r=Entry(aNewName,entry);
  1115 	if (r!=KErrNotFound)
  1116 		{
  1117 		if (r!=KErrNone)
  1118 			return(r);
  1119 		if (entry.IsDir() || entry.IsReadOnly())
  1120 			return(KErrAccessDenied);
  1121 		if (LocateFile(aNewName))
  1122 			return(KErrInUse);
  1123 		}
  1124 	r=Entry(anOldName,entry);
  1125 	if (r!=KErrNone)
  1126 		return(r);
  1127 	if (entry.IsDir() || IsWriteProtected())
  1128 		return(KErrAccessDenied);
  1129 	if (LocateFile(anOldName))
  1130 		return(KErrInUse);
  1131 
  1132 	// remove from closed queue
  1133 	LocateClosedFile(anOldName, EFalse);
  1134 	LocateClosedFile(aNewName, EFalse);
  1135 
  1136 	TRACEMULT3(UTF::EBorder, UTraceModuleFileSys::ECMountCBReplaceL, EF32TraceUidFileSys, DriveNumber(), anOldName, aNewName);
  1137 	TRAP(r,CurrentMount().ReplaceL(anOldName,aNewName))
  1138 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReplaceLRet, EF32TraceUidFileSys, r);
  1139 
  1140 	return(r);
  1141 	}
  1142 
  1143 TInt TDrive::Entry(const TDesC& aName,TEntry& anEntry)
  1144 //
  1145 // Get the entry details.
  1146 //
  1147 	{
  1148 	__CHECK_DRIVETHREAD(iDriveNumber);
  1149 	TInt r=CheckMountAndEntryName(aName);
  1150 	if (r!=KErrNone)
  1151 		return(r);
  1152 	TPtrC entryName(StripBackSlash(aName));
  1153 	TRAP(r,DoEntryL(entryName,anEntry));
  1154 	
  1155 	if (r==KErrHidden)
  1156 		r=KErrNotFound;	
  1157 	else if (r==KErrPathHidden)
  1158 		r=KErrPathNotFound;
  1159 
  1160 	return(r);
  1161 	}
  1162 
  1163 void TDrive::DoEntryL(const TDesC& aName, TEntry& anEntry)
  1164 //
  1165 // Get entry details
  1166 //
  1167 	{
  1168 	FlushCachedFileInfoL();
  1169 
  1170 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBEntryL, EF32TraceUidFileSys, DriveNumber(), aName);
  1171 	CurrentMount().EntryL(aName,anEntry);
  1172 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECMountCBEntryLRet, EF32TraceUidFileSys, 
  1173 		KErrNone, anEntry.iAtt, 
  1174 		I64LOW(anEntry.iModified.Int64()), I64HIGH(anEntry.iModified.Int64()), 
  1175 		anEntry.iSize);
  1176 
  1177 	}
  1178 
  1179 TInt TDrive::CheckAttributes(const TDesC& aName,TUint& aSetAttMask,TUint& aClearAttMask)
  1180 //
  1181 // Validate the changes against the current entry attributes
  1182 //
  1183 	{
  1184 
  1185 	TEntry entry;
  1186 	TRAPD(r,DoEntryL(aName,entry));
  1187 	if (r!=KErrNone)
  1188 		return(r);
  1189 	ValidateAtts(entry.iAtt,aSetAttMask,aClearAttMask);
  1190 	return(KErrNone);
  1191 	}
  1192 
  1193 TInt TDrive::SetEntry(const TDesC& aName,const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
  1194 //
  1195 // Set the entry details.
  1196 //
  1197 	{
  1198 	__CHECK_DRIVETHREAD(iDriveNumber);
  1199 	TInt r=CheckMountAndEntryName(aName);
  1200 	if (r!=KErrNone)
  1201 		return(r);
  1202 	TPtrC entryName(StripBackSlash(aName));
  1203 	CFileCB* pF=LocateFile(entryName);
  1204 	if (pF!=NULL)
  1205 		return(KErrInUse);
  1206 	r=CheckAttributes(entryName,aSetAttMask,aClearAttMask);
  1207 	if (r!=KErrNone)
  1208 		return(r);
  1209 	if (IsWriteProtected())
  1210 		return(KErrAccessDenied);
  1211 	TTime nullTime(0);
  1212 	if (aTime!=nullTime)
  1213 		aSetAttMask|=KEntryAttModified;
  1214 
  1215 	TRACEMULT6(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetEntryL, EF32TraceUidFileSys, 
  1216 		DriveNumber(), aName, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSetAttMask, aClearAttMask);
  1217 	TRAP(r,CurrentMount().SetEntryL(entryName,aTime,aSetAttMask,aClearAttMask))
  1218 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetEntryLRet, EF32TraceUidFileSys, r);
  1219 
  1220 	return(r);
  1221 	}
  1222 
  1223 TInt TDrive::FileTemp(CFsRequest* aRequest,TInt& aHandle,const TDesC& aPath,TDes& aName,TUint aMode)
  1224 //
  1225 // Create a temporary file and return the file name.
  1226 //
  1227 	{
  1228 	__CHECK_DRIVETHREAD(iDriveNumber);
  1229 	aName=aPath;
  1230 	TInt len=aName.Length();
  1231 	TInt t=User::TickCount()&0xfffff;
  1232 	aMode|=EFileWrite;
  1233 	for (TInt retry=0;retry<KMaxTempNameAttempts;retry++)
  1234 		{
  1235 		aName.SetLength(len);
  1236 		aName.AppendFormat(_L("TMP%05x.$$$"),t);
  1237 		TEntry e;
  1238 		TInt r=Entry(aName,e);
  1239 		if (r!=KErrNone)
  1240 			{
  1241 			if (r!=KErrNotFound)
  1242 				return(r);
  1243 			return(FileOpen(aRequest,aHandle,aName,aMode,EFileCreate));
  1244 			}
  1245 		t=((t|1)*13)&0xfffff;
  1246 		}
  1247 	return(KErrGeneral);
  1248 	}
  1249 
  1250 LOCAL_C HBufC* CreateFileNameL(const TDesC& aName)
  1251 //
  1252 // Create a HBufC from aName
  1253 // Converts _L("\\F32.\\GROUP\\release.") to _L("\\F32\\GROUP\\release")
  1254 //
  1255 	{
  1256 	
  1257 	TParsePtrC name(aName);
  1258 	TFileName fileName;
  1259 	fileName.Append(KPathDelimiter);
  1260 	
  1261 	if (name.Path().Length())
  1262 		{
  1263 		TInt pos=0;
  1264 		TPtrC entry(NULL,0);
  1265 		FOREVER
  1266 			{
  1267 			NextInPath(name.Path(),entry,pos);
  1268 			if (entry.Length()==0)
  1269 				break;
  1270 			fileName.Append(entry);
  1271 			fileName.Append(KPathDelimiter);
  1272 			}
  1273 		}
  1274 
  1275 	fileName.Append(name.Name());
  1276 	if (name.Ext().Length()>1)
  1277 		fileName.Append(name.Ext());
  1278 	return(fileName.AllocL());
  1279 	} 
  1280 
  1281 void TDrive::FileOpenL(CFsRequest* aRequest,TInt& aHandle,const TDesC& aName,TUint aMode,TFileOpen anOpen,CFileCB*& aFileCB,CFileShare*& aFileShare)
  1282 //
  1283 // Open/Create/Replace a file.
  1284 //
  1285 	{
  1286 	aFileCB=NULL;
  1287 	aFileShare=NULL;
  1288 	TInt r = CheckMount();
  1289 	if (r!=KErrNone)
  1290 		User::Leave(r);
  1291 
  1292 	if (IsIllegalFullName(aRequest->Src()))
  1293 		User::Leave(KErrBadName);
  1294 
  1295 	if (CurrentMount().Locked())
  1296 		User::Leave(KErrInUse);
  1297 
  1298 	if ((aMode & EFileWrite) != 0)
  1299 		{
  1300 		TDriveInfo driveInfo;
  1301 		DriveInfo(driveInfo);
  1302 		if (driveInfo.iType==EMediaRom || (driveInfo.iMediaAtt&KMediaAttWriteProtected)!=0)
  1303 			User::Leave(KErrAccessDenied);
  1304 		}
  1305 
  1306 	TShare share=(TShare)(aMode&KFileShareMask);
  1307 	if (share==EFileShareReadersOnly && (aMode&EFileWrite)!=0)
  1308 		User::Leave(KErrArgument);
  1309 	
  1310 	if (aMode & EFileReadAsyncAll)
  1311 		{
  1312 		// Async read all mode is not compatible with EFileShareExclusive or EFileShareReadersOnly,
  1313 		// as these modes prevent a writer from accessing the file and completing the request.
  1314 		if(share == EFileShareExclusive || share == EFileShareReadersOnly)
  1315 			User::Leave(KErrArgument);
  1316 		}
  1317 
  1318 	// check for silly cache on / off combinations
  1319 	const TUint KBadWriteMode = EFileWriteBuffered | EFileWriteDirectIO;
  1320 	const TUint KBadReadMode = EFileReadBuffered | EFileReadDirectIO;
  1321 	const TUint KBadReadAheadMode = EFileReadAheadOn | EFileReadAheadOff;
  1322 	const TUint KBadReadAheadMode2 = EFileReadDirectIO | EFileReadAheadOn;
  1323 	if (((aMode & KBadWriteMode) == KBadWriteMode) ||
  1324 		((aMode & KBadReadMode) == KBadReadMode) ||
  1325 		((aMode & KBadReadAheadMode) == KBadReadAheadMode) ||
  1326 		((aMode & KBadReadAheadMode2) == KBadReadAheadMode2))
  1327 		{
  1328 		User::Leave(KErrArgument);
  1329 		}
  1330 
  1331 	// Only allow delete on close for a newly created file.
  1332 	if ((aMode & EDeleteOnClose) && (anOpen!=EFileCreate))
  1333 		User::Leave(KErrArgument);
  1334 
  1335 	CFileCB* pF=LocateFile(aName);
  1336 	CFileCache* pFileCache = NULL;
  1337 	TBool openFile=EFalse;
  1338 	if (pF!=NULL)
  1339 		{
  1340 		if (pF->iShare==EFileShareReadersOnly && (aMode&EFileWrite)!=0)
  1341 			User::Leave(KErrInUse);
  1342 		if (anOpen==EFileCreate)
  1343 			User::Leave(KErrAlreadyExists);
  1344 		TInt r=ValidateShare(*pF,share);
  1345 		if (r!=KErrNone)
  1346 			User::Leave(r);
  1347 		if ((r=pF->Open())!=KErrNone)
  1348 			User::Leave(r);
  1349 		aFileCB=pF;
  1350 		pFileCache = pF->FileCache();
  1351 		}
  1352 	else
  1353 		{
  1354 		TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  1355 
  1356         //-- construct CFileCB object, belonging to the corresponding mount
  1357         pF = aFileCB = CurrentMount().NewFileL();
  1358 
  1359 		TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileLRet, EF32TraceUidFileSys, r, pF);
  1360 		TDrive* createdDrive=!aRequest->SubstedDrive() ? this : aRequest->SubstedDrive();
  1361 
  1362     	HBufC* fileName = CreateFileNameL(aName);
  1363 
  1364         pF->InitL(this, createdDrive, fileName);
  1365 
  1366 
  1367 		pF->iShare = share;
  1368 		openFile=ETrue;
  1369 		CurrentMount().iMountQ.AddLast(*pF);
  1370 		Files->AddL(pF,ETrue);
  1371 		}
  1372 	
  1373     CFileShare* pS=aFileShare=new(ELeave) CFileShare(pF);
  1374 
  1375 	// We need to call CFileCB::PromoteShare immediately after the CFileShare 
  1376 	// instance is created since the destructor calls CFileCB::DemoteShare()
  1377 	// which checks the share count is non-zero
  1378 	pS->iMode=aMode;
  1379 	pF->PromoteShare(pS);
  1380 
  1381 	pS->InitL();
  1382 	aFileCB=NULL; 
  1383 	FileShares->AddL(pS,ETrue);
  1384 	aHandle=aRequest->Session()->Handles().AddL(pS,ETrue);
  1385 
  1386 
  1387 	if (openFile)
  1388 		{
  1389 		TRACEMULT5(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenL, EF32TraceUidFileSys, DriveNumber(), aName, aMode, (TUint) anOpen, (TUint) pF);
  1390 		CurrentMount().FileOpenL(aName,aMode,anOpen,pF);
  1391 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenLRet, EF32TraceUidFileSys, KErrNone);
  1392 
  1393 		// Delete on close may now be safely flagged if required.
  1394 		// The file did not exist on the media prior to the
  1395 		// CMountCB::FileOpenL() call for the case of a create.
  1396 		if ((aMode & EDeleteOnClose) && (anOpen==EFileCreate))
  1397 			pF->SetDeleteOnClose();
  1398 
  1399 		TBool localBufferSuppport = (CurrentMount().LocalBufferSupport(pF) == KErrNone)?(TBool)ETrue:(TBool)EFalse;
  1400 		pF->SetLocalBufferSupport(localBufferSuppport);
  1401 		if (localBufferSuppport)
  1402 			{
  1403 			// if file exists on closed queue resurrect it or discard it,
  1404 			// depending on the file open mode
  1405 			pFileCache = LocateClosedFile(aName, anOpen == EFileOpen?(TBool)ETrue:(TBool)EFalse);
  1406 			if (pFileCache)
  1407 				{
  1408 				pFileCache = pFileCache->ReNewL(*pS);	// NB may return NULL if caching not enabled
  1409 				}
  1410 			else
  1411 				{
  1412 				pFileCache = CFileCache::NewL(*pS);		// NB may return NULL if caching not enabled
  1413 				}
  1414 			if (pFileCache)
  1415 				// set the cached size to be the same as the uncached size
  1416 				pF->SetCachedSize64(pF->Size64());
  1417 			}
  1418 		else
  1419 			{
  1420 			__CACHE_PRINT(_L("TDrive::FileOpenL(), Local buffers not supported"));
  1421 			}
  1422 		}
  1423 
  1424 	// initialize share mode flags
  1425 	if (pFileCache != NULL)
  1426 		pFileCache->Init(*pS);
  1427 	}
  1428 
  1429 TInt TDrive::FileOpen(CFsRequest* aRequest,TInt& aHandle,const TDesC& aName,TUint aMode,TFileOpen anOpen)
  1430 //
  1431 // Open/Create/Replace a file.
  1432 //
  1433 	{
  1434 	__CHECK_DRIVETHREAD(iDriveNumber);
  1435 	CFileCB* pF=NULL;
  1436 	CFileShare* pS=NULL;
  1437 	aHandle=0;
  1438 	TRAPD(r,FileOpenL(aRequest,aHandle,aName,aMode,anOpen,pF,pS))
  1439 
  1440 	// Allow files > 2GB-1 to be opened only if EFileBigFile is specified in iMode
  1441 	if (r == KErrNone && pS && ((TUint64)pS->File().Size64() > KMaxLegacyFileSize) && (!(pS->IsFileModeBig())))
  1442 		r = KErrTooBig;
  1443 
  1444 	if (r!=KErrNone)
  1445 		{
  1446 		if (r==KErrHidden)
  1447 			r=KErrNotFound;	
  1448 		else if (r==KErrPathHidden)
  1449 			r=KErrPathNotFound;
  1450 
  1451 		if(pF && !pS)
  1452 			pF->Close();
  1453 		CheckSubClose(pS,aHandle,aRequest->Session());
  1454 		}
  1455 	return(r);
  1456 	}
  1457 
  1458 void TDrive::DirOpenL(CSessionFs* aSession,TInt& aHandle,const TDesC& aName,TUint anAtt,const TUidType& aUidType,CDirCB*& aDir)
  1459 //
  1460 // Open a directory listing. Leave on error.
  1461 //
  1462 	{
  1463 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewDirL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  1464 
  1465     CDirCB* pD = aDir = CurrentMount().NewDirL(); //-- construct CDirCB object, belonging to the corresponding mount
  1466 
  1467 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewDirLRet, EF32TraceUidFileSys, KErrNone, pD);
  1468 	pD->InitL(this);
  1469 	// modify resource counter after initialisation to ensure correct cleanup
  1470 	AddResource(CurrentMount());
  1471 	pD->iAtt=anAtt;
  1472 	pD->iUidType=aUidType;
  1473 	Dirs->AddL(pD,ETrue);
  1474 	aHandle=aSession->Handles().AddL(pD,ETrue);
  1475 
  1476 	TRACEMULT3(UTF::EBorder, UTraceModuleFileSys::ECMountCBDirOpenL, EF32TraceUidFileSys, DriveNumber(), aName, (TUint) pD);
  1477 	CurrentMount().DirOpenL(aName,pD);
  1478 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDirOpenLRet, EF32TraceUidFileSys, KErrNone);
  1479 	}
  1480 
  1481 TInt TDrive::DirOpen(CSessionFs* aSession,TInt& aHandle,const TDesC& aName,TUint anAtt,const TUidType& aUidType)
  1482 //
  1483 // Open a directory listing.
  1484 //
  1485 	{
  1486 	TInt r=CheckMountAndEntryName(aName);
  1487 	if (r!=KErrNone)
  1488 		return(r);
  1489 	if (CurrentMount().Locked())
  1490 		return(KErrInUse);
  1491 	CDirCB* pD=NULL;
  1492 	aHandle=0;
  1493 	TRAP(r,DirOpenL(aSession,aHandle,aName,anAtt,aUidType,pD));
  1494 	
  1495 	if (r==KErrHidden)
  1496 		r=KErrNotFound;	
  1497 	else if (r==KErrPathHidden)
  1498 		r=KErrPathNotFound;
  1499 
  1500 	if (r!=KErrNone)
  1501 		CheckSubClose(pD,aHandle,aSession);
  1502 	return(r);
  1503 	}
  1504 
  1505 
  1506 TInt TDrive::ReadFileSection(const TDesC& aName,TInt aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
  1507 //
  1508 //	Starting from aPos, read aLength bytes of a file into a Trg, 
  1509 //	regardless of lock state
  1510 //
  1511 	{
  1512 	return ReadFileSection64(aName, aPos, aTrg, aLength, aMessage);
  1513 	}
  1514 
  1515 
  1516 TInt TDrive::ReadFileSection64(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
  1517 //
  1518 //	Starting from aPos, read aLength bytes of a file into a Trg, 
  1519 //	regardless of lock state
  1520 //
  1521 	{
  1522 
  1523 	// flush dirty data if already open
  1524 	CFileCB* file;
  1525 	IsFileOpen(aName, file);
  1526 		if (file && file->FileCache())
  1527 		{
  1528 		if (file->FileCache()->FlushDirty() == CFsRequest::EReqActionBusy)
  1529 			return CFsRequest::EReqActionBusy;
  1530 		}
  1531 
  1532 	__PRINT(_L("TDrive::ReadSection"));
  1533 	TInt r=CheckMountAndEntryName(aName);
  1534 	if (r!=KErrNone)
  1535 		return(r);
  1536 	TPtrC entryName(StripBackSlash(aName));
  1537 
  1538 	TRACETHREADID(aMessage);
  1539 	TRACEMULT7(UTF::EBorder, UTraceModuleFileSys::ECMountCBReadFileSectionL, EF32TraceUidFileSys, 
  1540 		DriveNumber(), aName, I64LOW(aPos), I64HIGH(aPos), (TUint) aTrg, aLength, I64LOW(threadId));
  1541 	TRAP(r,ReadSectionL(entryName,aPos,aTrg,aLength,aMessage));
  1542 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReadFileSectionLRet, EF32TraceUidFileSys, r);
  1543 
  1544 	if (r==KErrHidden)
  1545 		r=KErrNotFound;	
  1546 	else if (r==KErrPathHidden)
  1547 		r=KErrPathNotFound;
  1548 
  1549 	return(r);
  1550 	}
  1551 
  1552 
  1553 void TDrive::ReadSectionL(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
  1554 //
  1555 //	Starting from aPos, read aLength bytes of a file into a Trg, 
  1556 //	regardless of lock state
  1557 //
  1558 	{
  1559 	__PRINT(_L("TDrive::ReadSectionL"));
  1560 	
  1561 	FlushCachedFileInfoL();
  1562 	CurrentMount().ReadSection64L(aName,aPos,aTrg,aLength,aMessage);
  1563 	}
  1564 
  1565 /**
  1566     Check the disk's integrity
  1567 */
  1568 TInt TDrive::CheckDisk()
  1569 	{
  1570 	TInt r=CheckMount();
  1571 	if (r==KErrNone)
  1572 		TRAP(r,FlushCachedFileInfoL());
  1573 	if (r==KErrNone)
  1574 		{
  1575 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk1, EF32TraceUidFileSys, DriveNumber());
  1576 		r=CurrentMount().CheckDisk();
  1577 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk1Ret, EF32TraceUidFileSys, r);
  1578 		}
  1579 	return(r);
  1580 	}
  1581 
  1582 /**
  1583     @prototype
  1584 */
  1585 TInt TDrive::CheckDisk(TInt aOperation, TAny* aParam1/*=NULL*/, TAny* aParam2/*=NULL*/)
  1586     {
  1587 	TInt r=CheckMount();
  1588 	if (r==KErrNone)
  1589 		TRAP(r,FlushCachedFileInfoL());
  1590 	if (r==KErrNone)
  1591 		{
  1592 		TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk2, EF32TraceUidFileSys, DriveNumber(), aOperation, aParam1, aParam2);
  1593 		r=CurrentMount().CheckDisk(aOperation, aParam1, aParam2);
  1594 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk2Ret, EF32TraceUidFileSys, r);
  1595 		}
  1596 
  1597 	return(r);
  1598     }
  1599 
  1600 TInt TDrive::ScanDrive()
  1601 	{
  1602 	__CHECK_DRIVETHREAD(iDriveNumber);
  1603 	TInt r=CheckMount();
  1604 	if(r==KErrNone)
  1605 		{
  1606 		if(IsWriteProtected())
  1607 			return(KErrAccessDenied);
  1608 		TRAP(r,FlushCachedFileInfoL());
  1609 		}
  1610 	if(r!=KErrNone)
  1611 		return r;
  1612 
  1613 	// Empty closed file queue
  1614 	TClosedFileUtils::Remove(DriveNumber());
  1615 
  1616 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive1, EF32TraceUidFileSys, DriveNumber());
  1617 	r = CurrentMount().ScanDrive();
  1618 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive1Ret, EF32TraceUidFileSys, r);
  1619 
  1620 	return r;
  1621 	}
  1622 
  1623 
  1624 /**
  1625     @prototype
  1626 */
  1627 TInt TDrive::ScanDrive(TInt aOperation, TAny* aParam1/*=NULL*/, TAny* aParam2/*=NULL*/)
  1628 	{
  1629 	__CHECK_DRIVETHREAD(iDriveNumber);
  1630 	TInt r=CheckMount();
  1631 	if(r==KErrNone)
  1632 		{
  1633 		if(IsWriteProtected())
  1634 			return(KErrAccessDenied);
  1635 		TRAP(r,FlushCachedFileInfoL());
  1636 		}
  1637 	if(r!=KErrNone)
  1638 		return r;
  1639 
  1640 	// Empty closed file queue
  1641 	TClosedFileUtils::Remove(DriveNumber());
  1642 
  1643 	TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive2, EF32TraceUidFileSys, DriveNumber(), aOperation, aParam1, aParam2);
  1644 	r = CurrentMount().ScanDrive(aOperation, aParam1, aParam2);
  1645 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive2Ret, EF32TraceUidFileSys, r);
  1646 
  1647 	return r;
  1648 	}
  1649 
  1650 
  1651 TInt TDrive::GetShortName(const TDesC& aName,TDes& aShortName)
  1652 //
  1653 // Get the short name associated with a long file name
  1654 //
  1655 	{
  1656 	TInt r=CheckMountAndEntryName(aName);
  1657 	if (r!=KErrNone)
  1658 		return(r);
  1659 	TPtrC entryName(StripBackSlash(aName));
  1660 
  1661 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetShortNameL, EF32TraceUidFileSys, DriveNumber(), entryName);
  1662 	TRAP(r,CurrentMount().GetShortNameL(entryName,aShortName));
  1663 	TRACERETMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetShortNameLRet, EF32TraceUidFileSys, r, aShortName);
  1664 
  1665 	return(r);
  1666 	}
  1667 
  1668 TInt TDrive::GetLongName(const TDesC& aShortName,TDes& aLongName)
  1669 //
  1670 // Get the long name associated with a short file name
  1671 //
  1672 	{
  1673 	TInt r=CheckMountAndEntryName(aShortName);
  1674 	if (r!=KErrNone)
  1675 		return(r);
  1676 	TPtrC entryName(StripBackSlash(aShortName));
  1677 
  1678 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetLongNameL, EF32TraceUidFileSys, DriveNumber(), entryName);
  1679 	TRAP(r,CurrentMount().GetLongNameL(entryName,aLongName));
  1680 	TRACERETMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetLongNameLRet, EF32TraceUidFileSys, r, aLongName);
  1681 
  1682 	return(r);
  1683 	}
  1684 
  1685 
  1686 /**
  1687     Query whether the file is open or not.
  1688 */
  1689 TInt TDrive::IsFileOpen(const TDesC& aFileName,CFileCB*& aFileCB)
  1690 	{
  1691 	__CHECK_DRIVETHREAD(iDriveNumber);
  1692 
  1693 	aFileCB = NULL;
  1694 	
  1695 	TInt r=CheckMountAndEntryName(aFileName);
  1696 	if (r!=KErrNone)
  1697 		return(r);
  1698     
  1699 	Files->Lock();
  1700 	TInt count=Files->Count();
  1701 
  1702 	// create a hash to speed up the search
  1703 
  1704 	TFileName foldedName;
  1705 	TUint32 nameHash=0;
  1706 	if (count > 0)
  1707 		{
  1708 		foldedName.CopyF(aFileName);
  1709 		nameHash=CalcNameHash(foldedName);
  1710 		}
  1711 
  1712 	while(count--)
  1713 		{
  1714 		CFileCB* file=(CFileCB*)(*Files)[count];
  1715 
  1716 		if ((&file->Drive()==this) && nameHash == file->NameHash() && file->FileNameF().Match(foldedName)!=KErrNotFound)
  1717 			{
  1718 			aFileCB = file;
  1719 			break;
  1720 			}
  1721 		}
  1722 	Files->Unlock();
  1723 	return(KErrNone);
  1724 	}
  1725 
  1726 TInt TDrive::IsFileInRom(const TDesC& aFileName,TUint8*& aFileStart)
  1727 //
  1728 // Return the start of the file if it is in rom
  1729 //
  1730 	{
  1731 	TInt r=CheckMount();
  1732 	if (r==KErrNone)
  1733 		CurrentMount().IsFileInRom(aFileName,aFileStart);
  1734 	return(r);
  1735 	}
  1736 
  1737 TBool TDrive::IsWriteProtected()
  1738 //
  1739 // return true if the media is write protected
  1740 //
  1741 	{
  1742 //	__CHECK_DRIVETHREAD(iDriveNumber);
  1743 	TDriveInfo drvInfo;
  1744 	drvInfo.iMediaAtt=0;
  1745 	if(Att() && iFSys)
  1746 		FSys().DriveInfo(drvInfo,DriveNumber());
  1747 	return((drvInfo.iMediaAtt&KMediaAttWriteProtected)!=0);
  1748 	}
  1749 
  1750 
  1751 
  1752 
  1753 /**
  1754 Checks whether any resource that could write to disk is open on
  1755 the current mount.
  1756 
  1757 @return True, if a resource that could write to disk is open on
  1758         the current mount, false otherwise.
  1759 */
  1760 EXPORT_C TBool TDrive::IsWriteableResource() const
  1761 	{
  1762 //	__CHECK_DRIVETHREAD(iDriveNumber);
  1763 	if(iCurrentMount==NULL)
  1764 		return(EFalse);
  1765 	if(iCurrentMount->LockStatus()>0)
  1766 		{
  1767 		// check format subsessions
  1768 		Formats->Lock();
  1769 		TInt count=Formats->Count();
  1770 		while(count--)
  1771 			{
  1772 			CFormatCB* format=(CFormatCB*)(*Formats)[count];
  1773 			if(&format->Mount()==iCurrentMount)
  1774 				{
  1775 				Formats->Unlock();
  1776 				return(ETrue);
  1777 				}
  1778 			}
  1779 		Formats->Unlock();
  1780 		// check raw disk subsessions
  1781 		RawDisks->Lock();
  1782 		count=RawDisks->Count();
  1783 		while(count--)
  1784 			{
  1785 			CRawDiskCB* rawDisk=(CRawDiskCB*)(*RawDisks)[count];
  1786 			if(&rawDisk->Mount()==iCurrentMount && !rawDisk->IsWriteProtected())
  1787 				{
  1788 				Formats->Unlock();
  1789 				return(ETrue);
  1790 				}
  1791 			}
  1792 		Formats->Unlock();
  1793 		}
  1794 	else if(iCurrentMount->LockStatus()<0)
  1795 		{
  1796 		// check file share subsessions
  1797 		FileShares->Lock();
  1798 		TInt count=FileShares->Count();
  1799 		while(count--)
  1800 			{
  1801 			CFileShare* fileShare=(CFileShare*)(*FileShares)[count];
  1802 			if (&fileShare->File().Mount()==iCurrentMount && ((fileShare->iMode&EFileWrite)!=0))
  1803 				{
  1804 				FileShares->Unlock();
  1805 				return(ETrue);
  1806 				}
  1807 			}
  1808 		FileShares->Unlock();
  1809 		}
  1810 	return(EFalse);
  1811 	}
  1812 
  1813 
  1814 
  1815 
  1816 /**
  1817 Tests whether the current function can cause a write to disk.
  1818 
  1819 @return True, if the current function can cause a write to disk,
  1820         false otherwise.
  1821 */
  1822 EXPORT_C TBool TDrive::IsCurrentWriteFunction() const
  1823 	{
  1824 //	__CHECK_DRIVETHREAD(iDriveNumber);
  1825 	CDriveThread* pT=NULL;
  1826 	TInt r=FsThreadManager::GetDriveThread(iDriveNumber, &pT);
  1827 	__ASSERT_ALWAYS(r==KErrNone && pT,Fault(EDriveCurrentWriteFunction));
  1828 	return(pT->IsRequestWriteable());
  1829 	}
  1830 
  1831 
  1832 
  1833 
  1834 TInt TDrive::ForceRemountDrive(const TDesC8* aMountInfo,TInt aMountInfoMessageHandle,TUint aFlags)
  1835 //
  1836 // Force a remount of the drive
  1837 //
  1838 	{
  1839 	__PRINT(_L("TDrive::ForceRemountDrive"));
  1840 	__CHECK_DRIVETHREAD(iDriveNumber);
  1841 	if(iFSys==NULL)
  1842 		return(KErrNotReady);
  1843 	TInt r;
  1844 	CMountCB* pM=NULL;
  1845 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  1846 	TRAP(r,pM=FSys().NewMountL());
  1847 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM);
  1848 	if(r!=KErrNone)
  1849 		return(r);
  1850 	pM->SetDrive(this);
  1851 
  1852 	TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBForceRemountDrive, EF32TraceUidFileSys, 
  1853 		DriveNumber(), aMountInfo, aMountInfoMessageHandle, aFlags);
  1854 	r=pM->ForceRemountDrive(aMountInfo,aMountInfoMessageHandle,aFlags);
  1855 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBForceRemountDriveRet, EF32TraceUidFileSys, r);
  1856 
  1857 	pM->Close();
  1858 	return(r);
  1859 	}
  1860 
  1861 TBool TDrive::IsExtensionMounted(CProxyDriveFactory* aFactory)
  1862 //
  1863 // return ETrue if extension mounted on the drive
  1864 //
  1865 	{
  1866 	for(TInt i=0;i<iExtInfo.iCount;++i)
  1867 		{
  1868 		if(iExtInfo.iInfo[i].iFactory==aFactory)
  1869 			return(ETrue);
  1870 		}
  1871 	return(EFalse);
  1872 	}
  1873 
  1874 TInt TDrive::MountExtension(CProxyDriveFactory* aFactory,TBool aIsPrimary)
  1875 //
  1876 // Mount an extension
  1877 //
  1878 	{
  1879 	__PRINT1(_L("TDrive::MountExtension aIsPrimary=%d"),aIsPrimary);
  1880 	if(aIsPrimary)
  1881 		{
  1882 		__CHECK_MAINTHREAD();
  1883 		// primary extension mounted before file system since it must be present
  1884 		// for successful mount
  1885 		__ASSERT_ALWAYS(!iFSys,Fault(EMountExtensionFSys));
  1886 		if(iExtInfo.iCount!=0)
  1887 			return(KErrAccessDenied);
  1888 		iExtInfo.iInfo[iExtInfo.iCount].iFactory=aFactory;
  1889 		iExtInfo.iInfo[iExtInfo.iCount++].iIsPrimary=ETrue;
  1890 		return(KErrNone);
  1891 		}
  1892 	__CHECK_DRIVETHREAD(iDriveNumber);
  1893 	// must be a secondary extension
  1894 	if(iFSys==NULL)
  1895 		return(KErrNotReady);
  1896 	TBool extSupported = iFSys->IsExtensionSupported();
  1897 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemIsExtensionSupported, EF32TraceUidFileSys, extSupported);
  1898 	if(!extSupported)
  1899 		return(KErrNotSupported);
  1900 	if(IsExtensionMounted(aFactory))
  1901 		return(KErrAlreadyExists);
  1902 	if(iCurrentMount && (CurrentMount().LockStatus()!=0 || Mount().Count()>1))
  1903 		return(KErrInUse);
  1904 	if(iExtInfo.iCount>=KMaxExtensionCount)
  1905 		return(KErrAccessDenied);
  1906 	iExtInfo.iInfo[iExtInfo.iCount].iFactory=aFactory;
  1907 	iExtInfo.iInfo[iExtInfo.iCount++].iIsPrimary=EFalse;
  1908 	// now dismount and mount so that the extension incorporated
  1909 	Dismount();
  1910 	TInt r=CheckMount();
  1911 	// if mount fails then remove the secondary extension
  1912 	if(r!=KErrNone)
  1913 		{
  1914 		--iExtInfo.iCount;
  1915 		__ASSERT_DEBUG(iExtInfo.iCount>=0,Fault(EExtensionInfoCount0));
  1916 		}
  1917 	return(r);
  1918 	}
  1919 
  1920 TInt TDrive::DismountExtension(CProxyDriveFactory* aFactory, TBool /*aIsPrimary*/)
  1921 //
  1922 // Dismount an extension
  1923 //
  1924 	{
  1925 	 __PRINT(_L("TDrive::DismountExtension"));
  1926 	 __CHECK_DRIVETHREAD(iDriveNumber);
  1927 
  1928 	// Empty closed file queue
  1929 	TClosedFileUtils::Remove(DriveNumber());
  1930 
  1931 	if(iExtInfo.iCount==0)
  1932 		return(KErrNotFound);
  1933 	if(iCurrentMount && (CurrentMount().LockStatus()!=0 || Mount().Count()>1))
  1934 		return(KErrInUse);
  1935 	for(TInt i=0;i<iExtInfo.iCount;++i)
  1936 		{
  1937 		if(iExtInfo.iInfo[i].iFactory==aFactory)
  1938 			{
  1939 			// cannot dismount a primary extension without dismounting the file system
  1940 			if(i==0 && iExtInfo.iInfo[i].iIsPrimary)
  1941 				return(KErrAccessDenied);
  1942 			// slide any remaining extensions down
  1943 			for(TInt j=i+1;j<iExtInfo.iCount;++j)
  1944 				iExtInfo.iInfo[j-1].iFactory=iExtInfo.iInfo[j].iFactory;
  1945 			iExtInfo.iCount--;
  1946 			__ASSERT_DEBUG(iExtInfo.iCount>=0,Fault(EExtensionInfoCount1));
  1947 			Dismount();
  1948 			return(KErrNone);
  1949 			}
  1950 		}
  1951 	return(KErrNotFound);
  1952 	}
  1953 
  1954 TInt TDrive::ExtensionName(TDes& aExtensionName,TInt aPos)
  1955 //
  1956 // Return the extension name
  1957 //
  1958 	{
  1959 	__CHECK_DRIVETHREAD(iDriveNumber);
  1960 
  1961 	if(iFSys==NULL)
  1962 		return(KErrNotReady);
  1963 
  1964 	if(aPos<iExtInfo.iCount)
  1965 		{
  1966 		aExtensionName=iExtInfo.iInfo[aPos].iFactory->Name();
  1967 		return(KErrNone);
  1968 		}
  1969 	return(KErrNotFound);
  1970 	}
  1971 
  1972 #if defined(_LOCKABLE_MEDIA)
  1973 	
  1974 TInt TDrive::LockDevice(TMediaPassword& aOld,TMediaPassword& aNew,TBool aStore)
  1975 //
  1976 // Lock media device
  1977 //
  1978 	{
  1979 	__PRINT(_L("TDrive::LockDevice"));
  1980 	__CHECK_DRIVETHREAD(iDriveNumber);
  1981 	if(iFSys==NULL)
  1982 		return(KErrNotReady);
  1983 	TInt r;
  1984 	CMountCB* pM=NULL;
  1985 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  1986 	TRAP(r,pM=FSys().NewMountL());
  1987 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM);
  1988 	if(r!=KErrNone)
  1989 		return(r);
  1990 	pM->SetDrive(this);
  1991 
  1992 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECMountCBLock, EF32TraceUidFileSys, DriveNumber(), aStore);
  1993 	r=pM->Lock(aOld,aNew,aStore);
  1994 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBLockRet, EF32TraceUidFileSys, r);
  1995 
  1996 	pM->Close();
  1997 	return(r);
  1998 	}
  1999 
  2000 TInt TDrive::UnlockDevice(TMediaPassword& aPassword,TBool aStore)
  2001 //
  2002 // Unlock media device
  2003 //
  2004 	{
  2005 	__PRINT(_L("TDrive::UnlockDevice"));
  2006 	__CHECK_DRIVETHREAD(iDriveNumber);
  2007 	if(iFSys==NULL)
  2008 		return(KErrNotReady);
  2009 	TInt r;
  2010 	CMountCB* pM=NULL;
  2011 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  2012 	TRAP(r,pM=FSys().NewMountL());
  2013 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM);
  2014 	if(r!=KErrNone)
  2015 		return(r);
  2016 
  2017 	// reset mount failure count - which is likely to be non-zero if drive is locked
  2018 	iMountFailures = 0;
  2019 
  2020 	pM->SetDrive(this);
  2021 
  2022 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECMountCBUnlock, EF32TraceUidFileSys, DriveNumber(), aStore);
  2023 	r=pM->Unlock(aPassword,aStore);
  2024 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBUnlockRet, EF32TraceUidFileSys, r);
  2025 
  2026 	pM->Close();
  2027 	return(r);
  2028 	}
  2029 
  2030 TInt TDrive::ClearDevicePassword(TMediaPassword& aPassword)
  2031 //
  2032 // Clear password of media device
  2033 //
  2034 	{
  2035 	__PRINT(_L("TDrive::ClearDevicePassword"));
  2036 	__CHECK_DRIVETHREAD(iDriveNumber);
  2037 	if(iFSys==NULL)
  2038 		return(KErrNotReady);
  2039 	TInt r;
  2040 	CMountCB* pM=NULL;
  2041 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  2042 	TRAP(r,pM=FSys().NewMountL());
  2043 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM);
  2044 	if(r!=KErrNone)
  2045 		return(r);
  2046 	pM->SetDrive(this);
  2047 
  2048 	// ClearPassword() will only work if the card is already unlocked. 
  2049 	// If the stack powers down, the card will become locked, so now that TBusLocalDrive::Caps()
  2050 	// no longer powers up ths stack, we need to unlock the card first - but ignore the error as 
  2051 	// the stack may unlock from the password store.
  2052 	TDriveInfo info;
  2053 	DriveInfo(info);
  2054 	if (info.iMediaAtt & KMediaAttLocked)
  2055 		UnlockDevice(aPassword, EFalse);
  2056 
  2057 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBClearPassword, EF32TraceUidFileSys, DriveNumber());
  2058 	r=pM->ClearPassword(aPassword);
  2059 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBClearPasswordRet, EF32TraceUidFileSys, r);
  2060 
  2061 	pM->Close();
  2062 	return(r);
  2063 	}
  2064 
  2065 TInt TDrive::EraseDevicePassword()
  2066 //
  2067 // Erase password from the media device
  2068 //
  2069 	{
  2070 	__PRINT(_L("TDrive::EraseDevicePassword"));
  2071 	__CHECK_DRIVETHREAD(iDriveNumber);
  2072 	if(iFSys==NULL)
  2073 		return(KErrNotReady);
  2074 	TInt r;
  2075 	CMountCB* pM=NULL;
  2076 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber());
  2077 	TRAP(r,pM=FSys().NewMountL());
  2078 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM);
  2079 	if(r!=KErrNone)
  2080 		return(r);
  2081 	pM->SetDrive(this);
  2082 
  2083 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBErasePassword, EF32TraceUidFileSys, DriveNumber());
  2084 	r=pM->ErasePassword();
  2085 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBErasePasswordRet, EF32TraceUidFileSys, r);
  2086 
  2087 	pM->Close();
  2088 	return(r);
  2089 	}
  2090 
  2091 #else
  2092 
  2093 TInt TDrive::LockDevice(TMediaPassword& /*aOld*/,TMediaPassword& /*aNew*/,TBool /*aStore*/)
  2094 //
  2095 // Lock media device
  2096 //
  2097 	{
  2098 	return(KErrNotSupported);
  2099 	}
  2100 
  2101 TInt TDrive::UnlockDevice(TMediaPassword& /*aPassword*/,TBool /*aStore*/)
  2102 //
  2103 // Unlock media device
  2104 //
  2105 	{
  2106 	return(KErrNotSupported);
  2107 	}
  2108 
  2109 TInt TDrive::ClearDevicePassword(TMediaPassword& /*aPassword*/)
  2110 //
  2111 // Clear password of media device
  2112 //
  2113 	{
  2114 	return(KErrNotSupported);
  2115 	}
  2116 
  2117 TInt TDrive::EraseDevicePassword(TMediaPassword& /*aPassword*/)
  2118 //
  2119 // Clear password of media device
  2120 //
  2121 	{
  2122 	return(KErrNotSupported);
  2123 	}
  2124 
  2125 #endif
  2126 
  2127 
  2128 
  2129 	
  2130 /**
  2131 Gets the current notification state, which indicates whether the client
  2132 is notified of any read or write failures.
  2133 
  2134 The notification status is a property of the current session with
  2135 the file server, the value of which is stored in CSessionFs::iNotifyUser.
  2136 If set to ETrue, the client will receive notifications from the file system.
  2137 
  2138 Called by CMountCB::GetNotifyUser().
  2139 
  2140 @return True, if the client receives notifications from the file system,
  2141         false otherwise.
  2142 
  2143 @see CMountCB
  2144 */	
  2145 EXPORT_C TBool TDrive::GetNotifyUser()
  2146 	{
  2147 	__CHECK_DRIVETHREAD(iDriveNumber);
  2148 	if(iDriveFlags & ENotifyOff)
  2149 		return(EFalse);
  2150 	else
  2151 		{
  2152 		CDriveThread* pT=NULL;
  2153 		
  2154         const TInt r=FsThreadManager::GetDriveThread(iDriveNumber,&pT);
  2155 		
  2156         //-- if this drive is synchronous, i.e. all requests are processed in the main FS thread,
  2157         //-- pretend that user notifications are turned off to avoid panic in the assert below.
  2158         //-- for synch. drives pT will always be NULL and it's not possible to obtain CSessionFs by drive number.
  2159         if(r == KErrAccessDenied) 
  2160             return EFalse;
  2161         
  2162 		__ASSERT_ALWAYS(r==KErrNone && pT,Fault(EDriveGetNotifyUser));
  2163 		return(pT->IsSessionNotifyUser());
  2164 		}
  2165 	}
  2166 
  2167 
  2168 
  2169 
  2170 /**
  2171 Dismounts the current mount. This is method is called from outside, so do some finalisation work on mount.
  2172 After calling this function there is no current mount on the drive.
  2173 */
  2174 EXPORT_C void TDrive::Dismount()
  2175 	{
  2176 	__PRINT1(_L("TDrive::Dismount() iCurrentMount:0x%x"),iCurrentMount);
  2177 
  2178 	iMountFailures = 0;
  2179 	if (!iCurrentMount)
  2180 		return;
  2181 
  2182     TRAP_IGNORE(FlushCachedFileInfoL());
  2183 
  2184     //-- try our best to finalise the mount (the mount can decide to do some job during finalisation, e.g. write some data)
  2185     TRAP_IGNORE(iCurrentMount->FinaliseMountL());
  2186     
  2187     DoDismount();
  2188 	}
  2189 
  2190 
  2191 
  2192 
  2193 /**
  2194 Forcibly dismounts the current mount and prevents it being remounted.
  2195 After calling this function there is no current mount on the drive.
  2196 */
  2197 void TDrive::ForceDismount()
  2198 	{
  2199 	__PRINT1(_L("TDrive::ForceDismount() iCurrentMount:0x%x"),iCurrentMount);
  2200 
  2201 	iMountFailures = 0;
  2202 
  2203 	if(!iCurrentMount)
  2204 		return;
  2205   
  2206 	TRAP_IGNORE(FlushCachedFileInfoL());
  2207 	iCurrentMount->SetDismounted(); //! this affects TDrive::ReMount()
  2208     DoDismount();
  2209 	}
  2210 
  2211 /** 
  2212     An internal method. Dismounts and closes a current mount. 
  2213     This method must not involve writing data to the media, because it could have beeen physically changed before.
  2214     Called only from TDrive::CheckMount().
  2215 */
  2216 void TDrive::DoDismount()
  2217     {
  2218     __PRINT1(_L("TDrive::DoDismount() iCurrentMount:0x%x"),iCurrentMount);
  2219 
  2220     iMountFailures = 0;
  2221 
  2222 	if (!iCurrentMount)
  2223 		return;
  2224 
  2225 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDismounted, EF32TraceUidFileSys, DriveNumber());
  2226     iCurrentMount->Dismounted();
  2227 	TRACE0(UTF::EBorder, UTraceModuleFileSys::ECMountCBDismountedRet, EF32TraceUidFileSys);
  2228 
  2229 	iCurrentMount->Close();
  2230 	iCurrentMount=NULL;
  2231     }
  2232 
  2233 
  2234 /**
  2235 Return the number of active mounts associated with this drive.
  2236 (inactive mounts are those that have been forcibly dismounted)
  2237 */
  2238 TInt TDrive::ActiveMounts() const
  2239 	{
  2240 	TInt activeMounts = 0;
  2241 
  2242 	TInt idx = Mount().Count();
  2243 	while(idx--)
  2244 		{
  2245 		if(((CMountCB*)Mount()[idx])->IsDismounted())
  2246 			{
  2247 			activeMounts++;
  2248 			}
  2249 		}
  2250 
  2251 	__PRINT1(_L("TDrive::ActiveMounts = %d"), activeMounts);
  2252 	return activeMounts;
  2253 	}
  2254 
  2255 
  2256 
  2257 
  2258 /**
  2259 Reactivate any disactive mounts on the drive following a dismount.
  2260 (inactive mounts are those that have been foribly dismounted)
  2261 */
  2262 void TDrive::ReactivateMounts()
  2263 	{
  2264 	__PRINT(_L("TDrive::ReactivateMounts"));
  2265 	
  2266 	TInt idx = Mount().Count();
  2267 	while(idx--)
  2268 		{
  2269 		((CMountCB*)Mount()[idx])->SetDismounted(EFalse);
  2270 		}
  2271 	}
  2272 
  2273 
  2274 
  2275 
  2276 /**
  2277 Increments the drive dismount lock.  This defers dismount
  2278 of a file system until all clients have notified that it
  2279 is safe to do so.
  2280 
  2281 @see RFs::NotifyDismount
  2282 */
  2283 void TDrive::DismountLock()
  2284 	{ iDismountLock++; }
  2285 
  2286 
  2287 
  2288 
  2289 /**
  2290 Decrements the drive dismount lock.  When the lock count
  2291 reaches zero, the file system may be unmounted
  2292 
  2293 @see RFs::AllowDismount
  2294 @return The new lock count
  2295 */
  2296 TInt TDrive::DismountUnlock()
  2297 	{ 
  2298 	return(--iDismountLock);
  2299 	}
  2300 
  2301 
  2302 
  2303 
  2304 /**
  2305 Return the state of the dismount lock.
  2306 */
  2307 TBool TDrive::DismountLocked() const
  2308 	{ return(iDismountLock); }
  2309 
  2310 
  2311 
  2312 
  2313 /**
  2314 Pending flag - set while waiting for clients to accept the dismount
  2315 */
  2316 void TDrive::SetDismountDeferred(TBool aPending)
  2317 	{
  2318 	if(aPending)
  2319 		iDriveFlags |= EDismountDeferred;
  2320 	else
  2321 		iDriveFlags &= ~EDismountDeferred;
  2322 	}
  2323 
  2324 
  2325 
  2326 TInt TDrive::ControlIO(const RMessagePtr2& aMessage,TInt aCommand,TAny* aParam1,TAny* aParam2)
  2327 //
  2328 // General purpose test interface - .FSY specific.
  2329 //
  2330 	{
  2331 	TInt r=CheckMount();
  2332 	if(r==KErrNone || (r==KErrInUse && iReason==KErrNone))
  2333 		{
  2334 		TRACETHREADID(aMessage);
  2335 		TRACE5(UTF::EBorder, UTraceModuleFileSys::ECMountCBControlIO, EF32TraceUidFileSys, 
  2336 			DriveNumber(), aCommand, aParam1, aParam2, I64LOW(threadId));
  2337 		r=CurrentMount().ControlIO(aMessage,aCommand,aParam1,aParam2);
  2338 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBControlIORet, EF32TraceUidFileSys, r);
  2339 		}
  2340 	return(r);
  2341 	}
  2342 
  2343 
  2344 
  2345 
  2346 /**
  2347 Gets the drive attributes
  2348 
  2349 @return The drive attributes.
  2350 */
  2351 EXPORT_C TUint TDrive::Att()
  2352 	{
  2353 	TUint a=iAtt;
  2354 	return(a);
  2355 	}
  2356 
  2357 void TDrive::SetAtt(TUint aValue)
  2358 //
  2359 // set drive attributes
  2360 //
  2361 	{
  2362 	iAtt=aValue;
  2363 	}
  2364 
  2365 EXPORT_C TBool TDrive::IsDriveThread() const
  2366 //
  2367 // Return ETrue if the current thread id is the same as that of the drive's drive thread
  2368 //
  2369 	{
  2370 	return(FsThreadManager::IsDriveThread(iDriveNumber,ETrue));
  2371 	}
  2372 
  2373 EXPORT_C TBool TDrive::IsMainThread() const
  2374 //
  2375 // Reture ETrue if the current thread id is the same as that of the main file server thread
  2376 //
  2377 	{
  2378 	return(FsThreadManager::IsMainThread());
  2379 	}
  2380 
  2381 EXPORT_C void TDrive::DriveFault(TBool aDriveError) const
  2382 //
  2383 //
  2384 //
  2385 	{
  2386 	if(aDriveError)
  2387 		::Fault(EFsDriveThreadError);
  2388 	else
  2389 		::Fault(EFsMainThreadError);
  2390 	}
  2391 
  2392 TInt TDrive::ClampFile(const TDesC& aName, TAny* aHandle)
  2393 //
  2394 // Attempt to clamp file
  2395 //
  2396 	{
  2397 	CMountCB* mount = (CMountCB*)&(CurrentMount());
  2398 	TInt driveNo = DriveNumber();
  2399 	return(mount->ClampFile(driveNo,aName,aHandle));
  2400 	}
  2401 
  2402 
  2403 TInt TDrive::UnclampFile(CMountCB* aMount, RFileClamp* aHandle)
  2404 //
  2405 // Attempt to unclamp file
  2406 //
  2407 	{
  2408 	return(aMount->UnclampFile(aHandle));
  2409 	}
  2410 
  2411 
  2412 TInt TDrive::ClampsOnDrive()
  2413 //
  2414 // Returns the number of clamps on this drive
  2415 //
  2416 	{
  2417 	Lock();
  2418 	TInt clamps = IsMounted()?((CMountCB*)&(CurrentMount()))->NoOfClamps():0;	
  2419 	UnLock();
  2420 	return (clamps);
  2421 	}
  2422 
  2423 
  2424 
  2425 void TDrive::SetClampFlag(TBool aClamped)
  2426 //
  2427 //	Indicate if any files are clamped
  2428 //
  2429 	{
  2430 	if(aClamped)
  2431 		iDriveFlags |= EClampPresent;
  2432 	else
  2433 		iDriveFlags &= ~EClampPresent;
  2434 	}
  2435 
  2436 
  2437 TBool TDrive::ClampFlag()
  2438 //
  2439 // Report if any files are clamped
  2440 //
  2441 	{ return(iDriveFlags & EClampPresent); }
  2442 
  2443 
  2444 
  2445 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  2446 TInt TDrive::ClearDeferredDismount()
  2447 // debug-only function for testing
  2448 	{
  2449 	Lock();
  2450 	FsNotify::HandleDismount(EFsDismountRegisterClient, DriveNumber(), ETrue, KErrNone);
  2451 	SetDismountDeferred(EFalse);
  2452 	UnLock();
  2453 	return KErrNone;
  2454 	}
  2455 #endif
  2456 	
  2457 
  2458 TInt TDrive::DismountProxyDrive()
  2459 //
  2460 // Dismount a proxy drive
  2461 //
  2462 	{
  2463 	 __PRINT(_L("TDrive::DismountProxyDrive"));
  2464 	 __CHECK_DRIVETHREAD(iDriveNumber);
  2465 
  2466 	if (!IsProxyDrive(iDriveNumber) || LocalDrives::DriveNumberToLocalDriveNumber(iDriveNumber) == KDriveInvalid)
  2467 		return KErrArgument;
  2468 
  2469 	if(iCurrentMount)
  2470 		return(KErrInUse);
  2471 
  2472 
  2473 	// Prevent ALL inactive mounts from EVER being remounted as they MAY (& probably do) point to
  2474 	// this proxy-drive which we are about to delete....
  2475 	// NB We could try to find out which mounts actually use this particular proxy-drive, but that's 
  2476 	// a bit tricky to determine if there are extensions present as CMountCB::ProxyDrive() will only 
  2477 	// return the first proxy drive in the chain.
  2478 	TInt mCount=Mount().Count();
  2479 	TInt u=(Mount().UniqueID()<<16);
  2480 	for (TInt i=0;i<mCount;i++)
  2481 		{
  2482 		CMountCB* pM=(CMountCB*)Mount().At(u|i);
  2483 		pM->SetProxyDriveDismounted();
  2484 		}
  2485 
  2486 	FsThreadManager::LockDrive(iDriveNumber);
  2487 	// Proxy drives are responsible for managing the drive threads...
  2488 	FsThreadManager::CloseDrive(iDriveNumber);
  2489 	LocalDrives::ClearProxyDriveMapping(iDriveNumber);
  2490 	FsThreadManager::UnlockDrive(iDriveNumber);
  2491 
  2492 	return KErrNone;
  2493 	}
  2494 
  2495 //----------------------------------------------------------------------------
  2496 /**
  2497     Complete, remove and delete notification requests
  2498     @param  aCompletionCode completion code for some notifications
  2499 */
  2500 void TDrive::DoCompleteDismountNotify(TInt aCompletionCode)
  2501     {
  2502     FsNotify::HandleDismount(EFsDismountRegisterClient, iDriveNumber, ETrue, KErrNone);
  2503 	FsNotify::HandleDismount(EFsDismountNotifyClients, iDriveNumber, ETrue, aCompletionCode);
  2504 	FsNotify::HandleDismount(EFsDismountForceDismount, iDriveNumber, ETrue, aCompletionCode);
  2505     }
  2506 
  2507 //----------------------------------------------------------------------------
  2508 /**
  2509     a helper method that allows forced dismounting current mount for volume formatting.
  2510 */
  2511 TInt TDrive::ForceUnmountFileSystemForFormatting()
  2512     {
  2513     TInt nRes;
  2514     
  2515     //-- check if there are any clamps on this drive
  2516     nRes = ClampsOnDrive();
  2517     if(nRes > 0)
  2518         return KErrInUse;
  2519 
  2520     //-- purge all dirty data in the files associated with this drive's mount
  2521     CDriveThread* pT=NULL;
  2522     nRes = FsThreadManager::GetDriveThread(DriveNumber(), &pT);
  2523     if(nRes == KErrNone && pT)
  2524         {
  2525         pT->CompleteReadWriteRequests();
  2526         }
  2527 
  2528     PurgeDirty(CurrentMount());
  2529 
  2530     //-- 
  2531 
  2532     ForceDismount();
  2533 
  2534     DoCompleteDismountNotify(KErrDisMounted); //-- complete all dismount notifications
  2535 
  2536     return KErrNone;
  2537     }
  2538 
  2539 //----------------------------------------------------------------------------- 
  2540 /** 
  2541     Instantiate CFormatCB object for formatting the file ssytem on the given TDrive.
  2542     
  2543     @param  aRequest            file server request object
  2544     @param  aFmtHandle          out: format handle
  2545     @param  aFmtMode            format mode
  2546     @param  apLDFormatInfo      pointer to legacy parameters structure; NULL means "not used"
  2547     @param  apVolFormatParam    pointer to the newparameters structure; NULL means "not used" 
  2548 
  2549     @return pointer to the instantiated CFormatCB object.
  2550 */
  2551 CFormatCB* TDrive::FormatOpenL(CFsRequest* aRequest, TInt& aFmtHandle, TFormatMode aFmtMode, const TLDFormatInfo* apLDFormatInfo, const TVolFormatParam* apVolFormatParam)
  2552     {
  2553     ASSERT(!(apLDFormatInfo && apVolFormatParam));  //-- these parameters are mutually exclusive
  2554     
  2555     TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFormatL, EF32TraceUidFileSys, &FSys(), DriveNumber()); 
  2556 
  2557     CFormatCB* pFormat = CurrentMount().NewFormatL(); 
  2558 
  2559 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFormatLRet, EF32TraceUidFileSys, KErrNone, pFormat); 
  2560 	
  2561     Formats->AddL(pFormat, ETrue); 
  2562 	pFormat->InitL(this, aFmtMode); 
  2563 
  2564     if(aFmtMode & ESpecialFormat) 
  2565         {
  2566         if(apLDFormatInfo)
  2567             {//-- the user has specified formatting parameters as TLDFormatInfo
  2568             pFormat->SetFormatParameters(apLDFormatInfo);
  2569             }
  2570         else if(apVolFormatParam && apVolFormatParam->SomeParamsSet())
  2571             {//-- the user has specified formatting parameters as TVolFormatParam
  2572             TInt nRes = pFormat->SetFormatParameters(apVolFormatParam);
  2573             User::LeaveIfError(nRes); //-- the particular file system might not support this feature
  2574             }
  2575         else
  2576             {//-- this is a special case, ESpecialFormat is set, but no parameters provided at all;
  2577              //-- invalidate CFormatCB::iSpecialInfo to make filesystem not to use it
  2578             pFormat->SetFormatParameters((TLDFormatInfo*)NULL);
  2579             }
  2580         }
  2581     
  2582 
  2583 	// modify resource counter after initialised to ensure correct cleanup 
  2584 	AddDiskAccess(CurrentMount());	 
  2585 	aFmtHandle = aRequest->Session()->Handles().AddL(pFormat, ETrue); 
  2586 
  2587     return pFormat;
  2588     }
  2589 
  2590 
  2591 
  2592 
  2593 
  2594 EXPORT_C void UNUSED1() {}
  2595 EXPORT_C void UNUSED2() {}
  2596 EXPORT_C void UNUSED3() {}
  2597 
  2598 
  2599 
  2600 
  2601 
  2602 
  2603 
  2604 
  2605