--- /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*)¬ification,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);
+ }