userlibandfileserver/fileserver/sfile/sf_ses.cpp
changeset 43 96e5fb8b040d
child 62 4a8fed1c0ef6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfile/sf_ses.cpp	Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,647 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32\sfile\sf_ses.cpp
+// 
+//
+
+#include "sf_std.h"
+#include "sf_file_cache.h"
+#include "sf_memory_man.h"
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION	
+#include "sf_notifier.h"
+#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION	
+
+CSessionFs::CSessionFs()
+	       :iSessionFlags((TInt)EFsSessionFlagsAll), 
+          iReservedDriveAccess(KReservedDriveAccessArrayGranularity, _FOFF(TReservedDriveAccess, iDriveNumber)),
+	       iId(0)
+	{
+	}
+
+CSessionFs *CSessionFs::NewL()
+	{
+	return new(ELeave) CSessionFs;
+	}
+
+CSessionFs::~CSessionFs()
+	{
+	__PRINT1(_L("CSessionFs::~CSessionFs() deleting... = 0x%x"),this);
+		
+	//take out all the reserved space set by this session
+	while(iReservedDriveAccess.Count())
+		{
+		TReservedDriveAccess& reserved = iReservedDriveAccess[0];
+		if(reserved.iReservedSpace)
+			{
+			TheDrives[reserved.iDriveNumber].SetReservedSpace(TheDrives[reserved.iDriveNumber].ReservedSpace() - reserved.iReservedSpace);
+			__ASSERT_DEBUG(TheDrives[reserved.iDriveNumber].ReservedSpace() >= 0,Fault(EReserveSpaceArithmetic));
+			}
+		iReservedDriveAccess.Remove(0);
+		}
+	iReservedDriveAccess.Close();
+	
+	
+	//	Need to free the requests that we own from the close queue
+	while (iCloseRequestCount > 0)
+		RequestAllocator::OpenSubFailed(this);
+	
+	if (iHandles)
+		delete iHandles;
+
+	
+	delete iPath;
+	iSessionFlagsLock.Close();
+	if(iDisconnectRequest)
+		delete(iDisconnectRequest);
+	}
+
+void CSessionFs::CreateL()
+//
+// Create any additional resources.
+//
+	{
+	__PRINT1(_L("CSessionFs::CreateL 0x%x"),this);
+
+	iHandles=CFsObjectIx::NewL();
+	TInt r = iSessionFlagsLock.CreateLocal();
+	User::LeaveIfError(r);
+	RMessage2 m;
+
+	iDisconnectRequest=new(ELeave) CFsDisconnectRequest;
+	iDisconnectRequest->Set(m,SessionDisconnectOp,this);
+
+
+	}
+
+TInt CSessionFs::CurrentDrive()
+//
+// Return the current drive.
+//
+	{
+
+	TInt d;
+	TInt r=RFs::CharToDrive(Path()[0],d);
+	__ASSERT_ALWAYS(r==KErrNone,Fault(ESesPathBadDrive));
+	return(d);
+	}
+
+TInt CSessionFs::CountResources()
+//
+// Return the number of resources owned by the session
+//
+	{
+	/* what's this supposed to be doing ??
+	TInt count=User::LockedInc(iResourceCount);
+	User::LockedDec(iResourceCount);
+	return(count);
+	*/
+
+	return iResourceCount;	// ... because that's all it does.
+	}
+
+void CSessionFs::ResourceCountMarkStart()
+//
+//	Mark resources at this point
+//
+	{
+	iResourceCountMark = CountResources();
+	}
+
+void CSessionFs::ResourceCountMarkEnd(const RMessage2& aMessage)
+//
+//	End resource count and check same as count start
+//
+	{
+	if (iResourceCountMark!=CountResources())
+		{
+		_LIT(KCategory,"CSessionFs");
+		aMessage.Panic(KCategory,ESesFoundResCountHeaven);
+		}
+	else
+		aMessage.Complete(KErrNone);
+	}
+
+void CSessionFs::Disconnect(const RMessage2& aMessage)
+	{
+	__THRD_PRINT1(_L("CSessionFs::Disconnect() 0x%x"),this);
+
+	iHandles->CloseMainThreadObjects();
+	iDisconnectRequest->SetMessage((RMessage2&)aMessage);
+
+	iDisconnectRequest->Dispatch();
+	}
+
+
+TUint CSessionFs::Reserved(TInt aDriveNumber) const
+	{
+	TReservedDriveAccess reserved(aDriveNumber);
+    TInt idx = iReservedDriveAccess.Find(reserved);
+    if(idx == KErrNotFound)
+        return 0;
+
+    return iReservedDriveAccess[idx].iReservedSpace;
+	}
+
+
+TInt CSessionFs::SetReserved(const TInt aDriveNumber, const TInt aReservedValue)
+	{
+	TReservedDriveAccess reserved(aDriveNumber, aReservedValue);
+	TInt idx = iReservedDriveAccess.Find(reserved);
+	if(idx == KErrNotFound)
+		return iReservedDriveAccess.InsertInSignedKeyOrder(reserved);
+
+	iReservedDriveAccess[idx].iReservedSpace = aReservedValue;
+	return KErrNone;
+
+	}
+
+
+TBool CSessionFs::ReservedAccess(TInt aDriveNumber) const
+	{
+	TReservedDriveAccess reserved(aDriveNumber);
+	TInt idx = iReservedDriveAccess.Find(reserved);
+	return idx == KErrNotFound ? EFalse : iReservedDriveAccess[idx].iReservedAccess;
+	}
+
+
+void CSessionFs::SetReservedAccess(const TInt aDriveNumber, const TBool aReservedAccess)
+	{
+	TReservedDriveAccess reserved(aDriveNumber);
+    TInt idx = iReservedDriveAccess.Find(reserved);
+    if(idx != KErrNotFound)
+        iReservedDriveAccess[idx].iReservedAccess = aReservedAccess;
+	}
+
+TBool CSessionFs::IsChangeNotify()
+	{
+	return TestSessionFlags(EFsSessionNotifyChange);
+	}
+
+
+TBool CSessionFs::TestSessionFlags(TUint32 aFlags)
+	{
+	iSessionFlagsLock.Wait();
+	TBool b = (iSessionFlags & aFlags) == aFlags;
+	iSessionFlagsLock.Signal();
+	return(b);
+	}
+
+
+void CSessionFs::SetSessionFlags(TUint32 aBitsToSet, TUint32 aBitsToClear)
+	{
+	iSessionFlagsLock.Wait();
+
+	iSessionFlags &= ~aBitsToClear;
+	iSessionFlags |= aBitsToSet;
+	
+	iSessionFlagsLock.Signal();
+	}
+
+void CSessionFs::CloseRequestCountInc()
+	{
+	iSessionFlagsLock.Wait();
+	iCloseRequestCount++;	
+	iSessionFlagsLock.Signal();
+	}
+
+void CSessionFs::CloseRequestCountDec()
+	{
+	iSessionFlagsLock.Wait();
+	iCloseRequestCount--;
+	iSessionFlagsLock.Signal();
+	}
+
+//
+// Start resource count
+//
+TInt TFsResourceCountMarkStart::DoRequestL(CFsRequest* aRequest)
+	{
+	aRequest->Session()->ResourceCountMarkStart();
+	return(KErrNone);
+	}
+
+TInt TFsResourceCountMarkStart::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return KErrNone;
+	}
+
+
+//
+//  Check for resource heaven
+//
+TInt TFsResourceCountMarkEnd::DoRequestL(CFsRequest* aRequest)
+	{
+	aRequest->Session()->ResourceCountMarkEnd(aRequest->Message());
+	return(KErrNone);
+	}
+
+TInt TFsResourceCountMarkEnd::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return KErrNone;
+	}
+
+
+//
+// Return the number of resources owned by the session
+//
+TInt TFsResourceCount::DoRequestL(CFsRequest* aRequest)
+	{
+	TInt resCount=aRequest->Session()->CountResources();
+	TPckgC<TInt> pckg(resCount);
+	aRequest->WriteL(KMsgPtr0,pckg);
+	return(KErrNone);
+	}
+
+TInt TFsResourceCount::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return KErrNone;
+	}
+
+
+//
+// Set iNotifyUser
+//
+void CSessionFs::SetNotifyUser(TBool aNotification)
+	{
+	if(aNotification)
+		{
+		SetSessionFlags(EFsSessionNotifyUser, 0);
+		}
+	else
+		{
+		SetSessionFlags(0, EFsSessionNotifyUser);
+		}
+	}
+
+//
+// Get iNotifyUser
+//
+TBool CSessionFs::GetNotifyUser()
+	{
+	return TestSessionFlags(EFsSessionNotifyUser);
+	}
+
+//
+// Notify the user of any read or write failure
+//
+TInt TFsSetNotifyUser::DoRequestL(CFsRequest* aRequest)
+	{
+	TBool notification=aRequest->Message().Int0();
+	aRequest->Session()->SetNotifyUser(notification);
+	return(KErrNone);
+	}
+
+TInt TFsSetNotifyUser::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return KErrNone;
+	}
+
+
+//
+// Notify the user of any read or write failure
+//
+TInt TFsGetNotifyUser::DoRequestL(CFsRequest* aRequest)
+	{
+	TBool notification=aRequest->Session()->GetNotifyUser();
+	TPtrC8 pA((TUint8*)&notification,sizeof(TBool));
+	aRequest->WriteL(KMsgPtr0,pA);
+	return(KErrNone);
+	}
+
+TInt TFsGetNotifyUser::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return KErrNone;
+	}
+
+
+//
+// Get the drive name
+//
+TInt TFsGetDriveName::DoRequestL(CFsRequest* aRequest)
+	{
+	TInt driveNum=aRequest->Drive()->DriveNumber();
+	TFileName driveName;
+	if (TheDriveNames[driveNum]==NULL)
+		driveName.SetLength(0);
+	else
+		driveName=(*TheDriveNames[driveNum]);
+	aRequest->WriteL(KMsgPtr1,driveName);
+	return(KErrNone);
+	}
+
+
+TInt TFsGetDriveName::Initialise(CFsRequest* aRequest)
+	{
+	TInt r=ValidateDrive(aRequest->Message().Int0(),aRequest);
+	return(r);
+	}
+
+
+
+//
+// Set the drive name
+//
+TInt TFsSetDriveName::DoRequestL(CFsRequest* aRequest)
+	{
+	TInt driveNum=aRequest->Drive()->DriveNumber();
+	TFileName driveName;
+	aRequest->ReadL(KMsgPtr1,driveName);
+
+//	Validate name - return KErrBadName if it contains illegal characters such as
+//	* ? / | > <
+
+	TNameChecker checker(driveName);
+	TText badChar;
+	if (checker.IsIllegalName(badChar))
+		return(KErrBadName);
+	
+	TInt len=((driveName.Length()+31)>>5)<<5; // % 32
+	if (TheDriveNames[driveNum]==NULL)
+		TheDriveNames[driveNum]=HBufC::New(len);
+	else if (TheDriveNames[driveNum]->Des().MaxLength()<len)
+		{
+		HBufC* temp=TheDriveNames[driveNum]->ReAlloc(len);
+		if (temp==NULL)
+			return(KErrNoMemory);
+		TheDriveNames[driveNum]=temp;
+		}
+	if (TheDriveNames[driveNum]==NULL || TheDriveNames[driveNum]->Des().MaxLength()<len)
+		return(KErrNoMemory);
+	*TheDriveNames[driveNum]=driveName;
+	return(KErrNone);
+	}
+
+TInt TFsSetDriveName::Initialise(CFsRequest* aRequest)
+	{
+	TInt r=ValidateDrive(aRequest->Message().Int0(),aRequest);
+	if (r!=KErrNone)
+		return(r);
+	if (!KCapFsSetDriveName.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Set Drive Name")))
+		return KErrPermissionDenied;
+	return KErrNone;
+	}
+
+TInt FlushCachedFiles(CSessionFs* aSession)
+	{
+	TInt retVal = KErrNone;
+
+	aSession->Handles().Lock();
+	TInt count = aSession->Handles().Count();
+	for (TInt n=0; n<count; n++)
+		{
+		CObjPromotion* obj = (CObjPromotion*)aSession->Handles()[n];
+		if (obj != NULL && obj->UniqueID() == FileShares->UniqueID())
+			{
+			CFileShare* share = (CFileShare*) obj;
+			if (!share->IsCorrectThread())
+				continue;
+			CFileCB& file=((CFileShare*) obj)->File();
+
+			CFileCache* fileCache = file.FileCache();
+			if (fileCache)
+				{
+				retVal = fileCache->FlushDirty();
+				if (retVal == CFsRequest::EReqActionBusy)
+					break;
+				}
+			}
+		}
+	aSession->Handles().Unlock();
+
+	return retVal;
+	}
+
+TInt TFsFlushDirtyData::DoRequestL(CFsRequest* aRequest)
+//
+//
+//
+	{
+	__CHECK_DRIVETHREAD(aRequest->DriveNumber());
+
+	// Flush all dirty data
+	TInt r = FlushCachedFiles(aRequest->Session());
+	if (r == CFsRequest::EReqActionBusy)
+		return r;
+	return KErrNone;
+	}
+
+TInt TFsFlushDirtyData::Initialise(CFsRequest* /*aRequest*/)
+//
+//
+//
+	{
+	return(KErrNone);
+	}
+
+
+// Iterate though all file shares owned by this session and cancel any async requests
+TInt CancelAsyncRequests(CSessionFs* aSession)
+	{
+	TInt retVal = KErrNone;
+
+	aSession->Handles().Lock();
+	TInt count = aSession->Handles().Count();
+	for (TInt n=0; n<count; n++)
+		{
+		CObjPromotion* obj = (CObjPromotion*)aSession->Handles()[n];
+		if (obj != NULL && obj->UniqueID() == FileShares->UniqueID())
+			{
+			CFileShare* share = (CFileShare*) obj;
+			if (!share->IsCorrectThread())
+				continue;
+			CFileCB& file=((CFileShare*) obj)->File();
+			file.CancelAsyncReadRequest(share, NULL);
+			}
+		}
+	aSession->Handles().Unlock();
+
+	return retVal;
+	}
+
+
+
+TInt TFsCancelSession::DoRequestL(CFsRequest* aRequest)
+	{
+	__CHECK_DRIVETHREAD(aRequest->DriveNumber());
+
+	// Cancel any outstanding requests
+	CDriveThread* pT=NULL;
+	TInt r=FsThreadManager::GetDriveThread(aRequest->DriveNumber(), &pT);
+	if(r==KErrNone)
+		pT->CompleteSessionRequests(aRequest->Session(),KErrCancel);
+	// We must also cancel any ASYNC requests belonging to this session BEFORE 
+	// ~CSessionFs() is called to avoid a KERN-EXEC 44 (EBadMessageHandle)
+	CancelAsyncRequests(aRequest->Session());
+	return(r);
+	}
+
+TInt TFsCancelSession::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return(KErrNone);
+	}
+
+TInt TFsSessionDisconnect::DoRequestL(CFsRequest* aRequest)
+	{
+	__PRINT(_L("TFsSessionDisconnect::DoRequestL()"));
+	__ASSERT_DEBUG(FsThreadManager::IsDisconnectThread(),Fault(ESessionDisconnectThread1));
+	CDisconnectThread* pT=FsThreadManager::GetDisconnectThread();
+	
+	// Complete requests on all plugins
+	CFsInternalRequest* pR=pT->GetRequest();
+	FsPluginManager::CompleteSessionRequests(aRequest->Session(), KErrCancel, pR);
+
+	// ...and on all drives
+	for(TInt i=0;i<KMaxDrives;++i)
+		{
+		FsThreadManager::LockDrive(i);
+		if(!FsThreadManager::IsDriveAvailable(i,EFalse)||FsThreadManager::IsDriveSync(i,EFalse))
+			{
+			FsThreadManager::UnlockDrive(i);
+			continue;
+			}
+		pR->Set(CancelSessionOp,aRequest->Session());
+		pR->SetDriveNumber(i);
+		pR->Status()=KRequestPending;
+		pR->Dispatch();
+		FsThreadManager::UnlockDrive(i);
+		User::WaitForRequest(pR->Status());
+		// check request completed or cancelled (by file system dismount which completes requests with KErrNotReady)
+		__ASSERT_ALWAYS(pR->Status().Int()==KErrNone||pR->Status().Int()==KErrNotReady,Fault(ESessionDisconnectThread2));
+		__THRD_PRINT2(_L("cancel session requests on drive %d r=%d"),i,pR->Status().Int());
+
+		if (TFileCacheSettings::Flags(i) & (EFileCacheWriteEnabled | EFileCacheWriteOn))
+			{
+			FsThreadManager::LockDrive(i);
+			if(!FsThreadManager::IsDriveAvailable(i,EFalse)||FsThreadManager::IsDriveSync(i,EFalse))
+				{
+				FsThreadManager::UnlockDrive(i);
+				continue;
+				}
+
+			// Flush dirty data
+			pR->Set(FlushDirtyDataOp,aRequest->Session());
+			pR->SetDriveNumber(i);
+			pR->Status()=KRequestPending;
+			pR->Dispatch();
+			FsThreadManager::UnlockDrive(i);
+			User::WaitForRequest(pR->Status());
+			// check request completed or cancelled (by file system dismount which completes requests with KErrNotReady)
+			__ASSERT_ALWAYS(pR->Status().Int()==KErrNone||pR->Status().Int()==KErrNotReady,Fault(ESessionDisconnectThread2));
+			__THRD_PRINT2(_L("Flush dirty data on drive %d r=%d"),i,pR->Status().Int());
+			}
+
+		}
+	FsNotify::CancelSession(aRequest->Session());
+	
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+	FsNotificationManager::RemoveNotificationRequest(aRequest->Session());
+#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+
+
+	// don't delete session here, will be done in CFsDisconnectRequest::Complete()
+	return(KErrNone);
+	}
+
+TInt TFsSessionDisconnect::Initialise(CFsRequest* /*aRequest*/)
+	{
+	return(KErrNone);
+	}
+
+TInt TFsCancelPlugin::DoRequestL(CFsRequest* aRequest)
+	{
+	//__ASSERT_DEBUG(FsPluginManager::IsPluginThread(),Fault(EFsPluginThreadError));
+	FsPluginManager::CancelPlugin(aRequest->iCurrentPlugin,aRequest->Session());
+	TInt err = aRequest->iCurrentPlugin->SessionDisconnect(aRequest->Session());
+	return(err);
+	}
+
+TInt TFsCancelPlugin::Initialise(CFsRequest* /*aRequest*/)
+	{
+	// Notify plugin of session disconnect
+	return(KErrNone);
+	}
+
+TInt TFsSetSessionFlags::DoRequestL(CFsRequest* aRequest)
+	{
+	aRequest->Session()->SetSessionFlags(aRequest->Message().Int0(), aRequest->Message().Int1());
+	return(KErrNone);
+	}
+
+TInt TFsSetSessionFlags::Initialise(CFsRequest* aRequest)
+	{
+	if (!KCapFsPlugin. CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Set Session Flags")))
+		return KErrPermissionDenied;
+	return KErrNone;
+	}
+
+TInt TFsInitialisePropertiesFile::DoRequestL(CFsRequest* aRequest)
+	{
+	__PRINT(_L("**TFsInitialisePropertiesFile::DoRequestL**\n"));
+	TInt err = KErrNone;
+	TInt leaveErr = KErrNone;
+	const TBool isRomParam = aRequest->Message().Int2();
+	if(isRomParam)
+		{
+		const TAny* romAddress = aRequest->Message().Ptr0();
+		TBool isInRom = EFalse;
+		TRAP(leaveErr, User::IsRomAddress(isInRom, const_cast<TAny*>(romAddress)));
+		if (leaveErr == KErrNone)
+			{
+			const TInt length = aRequest->Message().Int1();
+			err = isInRom ? F32Properties::Initialise((TInt)romAddress, length) : KErrNotSupported;
+			}
+		}
+	else
+		{
+		err = KErrNotSupported;
+		}
+
+#ifdef SYMBIAN_ENABLE_FAT_DIRECTORY_OPT
+	// Create the global cache memory manager for FAT dir cache (and other caches).
+	// Note: file cache uses its own cache memory manager.
+	if (CCacheMemoryManagerFactory::CacheMemoryManager() == NULL)
+		{
+		TGlobalCacheMemorySettings::ReadPropertiesFile();
+		TRAPD(r, CCacheMemoryManagerFactory::CreateL());
+		__ASSERT_ALWAYS(r==KErrNone,Fault(ECacheMemoryManagerCreateFailed));
+		}
+#endif // SYMBIAN_ENABLE_FAT_DIRECTORY_OPT
+
+	// Create the page cache for file caching etc.
+	TGlobalFileCacheSettings::ReadPropertiesFile();
+	if (TGlobalFileCacheSettings::Enabled())
+		{
+		TRAPD(r, CCacheManagerFactory::CreateL());
+		__ASSERT_ALWAYS(r==KErrNone,Fault(EFileCacheCreateFailed));
+		}
+
+	User::LeaveIfError(leaveErr);
+	return(err);
+	}
+
+TInt TFsInitialisePropertiesFile::Initialise(CFsRequest* aRequest)
+	{
+	if (!KCapDiskAdmin. CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Initialise Property File")))
+		{
+		return(KErrPermissionDenied);
+		}
+    
+	if (aRequest->Message().SecureId() != KEstartUidValue)
+		{
+        return(KErrPermissionDenied);
+		}
+
+	aRequest->SetDriveNumber(EDriveZ);
+	return(KErrNone);
+	}