sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32\sfile\sf_svr.cpp sl@0: // sl@0: // sl@0: sl@0: #include "sf_std.h" sl@0: #include "sf_cache_man.h" sl@0: #include "sf_file_cache.h" sl@0: #include "sf_memory_man.h" sl@0: sl@0: TInt DoFsSubClose(CFsRequest* aRequest) sl@0: // sl@0: // Close a subsession. sl@0: // sl@0: { sl@0: const TInt handle(aRequest->Message().Int3()); sl@0: sl@0: CFsObject* pO=SessionObjectFromHandle(handle,0,aRequest->Session()); sl@0: if(!pO) sl@0: return KErrBadHandle; sl@0: sl@0: aRequest->Session()->DecResourceCount(); sl@0: aRequest->Session()->Handles().Remove(handle,ETrue); sl@0: sl@0: // this request has also opened this object, so close it here before it sl@0: // gets to a plugin as a plugin may attempt to open the file/dir itself sl@0: aRequest->SetScratchValue64( MAKE_TUINT64(I64HIGH(aRequest->ScratchValue64()), 0)); sl@0: sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: TInt TFsSubClose::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Close a subsession. sl@0: // sl@0: { sl@0: sl@0: // Leave and then panic client with KErrBadHandle if necessary. sl@0: CFsObject* pO = SessionObjectFromHandle(aRequest->Message().Int3(),0,aRequest->Session()); sl@0: if(!pO) sl@0: return KErrBadHandle; sl@0: sl@0: if(aRequest->Message().Function() == EFsFileSubClose) sl@0: { sl@0: CFileShare* pShare = (CFileShare*) aRequest->ScratchValue(); sl@0: sl@0: // flush the file cache sl@0: CFileCache* fileCache = pShare->File().FileCache(); sl@0: if (fileCache && fileCache->FlushDirty(aRequest) == CFsRequest::EReqActionBusy) sl@0: return CFsRequest::EReqActionBusy; sl@0: sl@0: // if any write requests are being fair scheduled, wait for them to complete sl@0: if (pShare->RequestInProgress()) sl@0: return CFsRequest::EReqActionBusy; sl@0: } sl@0: sl@0: return DoFsSubClose(aRequest); sl@0: } sl@0: sl@0: TInt TFsSubClose::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // Now moved to RequestAllocator::GetRequest sl@0: // sl@0: { sl@0: TInt r = KErrNone; sl@0: // Closing a file share may require flushing of dirty data, so deal with this in the drive thread sl@0: // in TFsSubClose::DoRequestL(). For other objects (EFsFormatSubClose, EFsDirSubClose, EFsRawSubClose, sl@0: // FsPluginSubClose) we may complete the message here. sl@0: if(aRequest->FsFunction() == EFsFileSubClose) sl@0: { sl@0: CFileShare* pShare = (CFileShare*) sl@0: SessionObjectFromHandle(aRequest->Message().Int3(), FileShares->UniqueID(), aRequest->Session()); sl@0: sl@0: if(!pShare) sl@0: User::Leave(KErrBadHandle); sl@0: sl@0: HBufC* pFileName = pShare->File().FileName().Alloc(); sl@0: aRequest->SetScratchValue64( MAKE_TUINT64((TUint) pFileName, (TUint) pShare) ); sl@0: TInt driveNumber = pShare->File().Drive().DriveNumber(); sl@0: aRequest->SetDriveNumber(driveNumber); sl@0: } sl@0: sl@0: // Define a completion routine so that we can see whether this request is cancelled - sl@0: // if it is we still want to close the subsession (but not bother about flushing dirty data) sl@0: r = ((CFsMessageRequest*) aRequest)->PushOperation(TFsSubClose::Complete); sl@0: sl@0: sl@0: sl@0: return r; sl@0: } sl@0: sl@0: TInt TFsSubClose::Complete(CFsRequest* aRequest) sl@0: { sl@0: // if LastError() != KErrNone, this implies the request has been cancelled. sl@0: // i.e. TFsSubClose::DoRequestL() has not been called, so we need to call DoFsSubClose() here sl@0: if (((CFsMessageRequest*) aRequest)->LastError() != KErrNone) sl@0: DoFsSubClose(aRequest); sl@0: sl@0: return CFsRequest::EReqActionComplete; sl@0: } sl@0: sl@0: sl@0: TInt TFsNotifyChange::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: CStdChangeInfo* notificationInfo=new CStdChangeInfo; sl@0: if (notificationInfo==NULL) sl@0: return (KErrNoMemory); sl@0: const RMessage2& m=aRequest->Message(); sl@0: notificationInfo->Initialise((TNotifyType)m.Int0(),(TRequestStatus*)m.Ptr1(),m,aRequest->Session()); sl@0: TInt r=FsNotify::AddChange(notificationInfo,KDriveInvalid); sl@0: if(r!=KErrNone) sl@0: delete(notificationInfo); sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: TInt TFsNotifyChange::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsNotifyChangeEx::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Set up an extended change notification sl@0: // sl@0: { sl@0: TUint notifyType=aRequest->Message().Int0(); sl@0: if (aRequest->Src().NamePresent()) // Monitoring a file sl@0: { // Reject if iNotifyType is ENotifyDir sl@0: if (notifyType&ENotifyDir) sl@0: return (KErrArgument); sl@0: } sl@0: CExtChangeInfo* notificationInfo=new CExtChangeInfo; sl@0: if (notificationInfo==NULL) sl@0: return (KErrNoMemory); sl@0: /* TEntry t; sl@0: TInt ret=aRequest->Drive()->Entry(aRequest->Src().FullName().Mid(2),t); sl@0: if ((ret==KErrNotFound)||(ret==KErrPathNotFound)||(ret==KErrInUse)) sl@0: // Path does not yet exist or drive has been locked - still submit request sl@0: // but mark it as notify all since the client is potentially interested sl@0: notifyType=ENotifyAll; sl@0: else if (ret!=KErrNone) sl@0: { sl@0: delete notificationInfo; sl@0: return(ret); sl@0: }*/ sl@0: sl@0: const RMessage2& m=aRequest->Message(); sl@0: notificationInfo->Initialise((TNotifyType)notifyType,(TRequestStatus*)m.Ptr2(),m,aRequest->Session(),aRequest->Src().FullName().Mid(2)); sl@0: TInt drive; sl@0: if (aRequest->ScratchValue()!=0) sl@0: drive=KDriveInvalid; sl@0: else sl@0: drive=aRequest->DriveNumber(); sl@0: TInt ret=FsNotify::AddChange(notificationInfo,drive); sl@0: if(ret!=KErrNone) sl@0: delete(notificationInfo); sl@0: return(ret); sl@0: } sl@0: sl@0: sl@0: TInt TFsNotifyChangeEx::Initialise(CFsRequest* aRequest) sl@0: { sl@0: // Establish whether the directory or file to watch actually exists sl@0: // This sets the aSession members iTheName and iTheParse etc sl@0: TInt ret=KErrNone; sl@0: TBool monitorAllDrives=EFalse; sl@0: TFileName notifyPath; sl@0: sl@0: TRAP(ret,aRequest->ReadL(KMsgPtr1,notifyPath)); sl@0: if(ret!=KErrNone) sl@0: return(ret); sl@0: if(notifyPath.Length()==0) sl@0: return(KErrArgument); sl@0: sl@0: if ((notifyPath[0]==KMatchAny)||(notifyPath[0]==KMatchOne)) sl@0: { sl@0: // Use the default session drive for now sl@0: // Client has submitted a ? or * for drive sl@0: monitorAllDrives=ETrue; sl@0: ret=ParseNotificationPath(aRequest,aRequest->Src(),notifyPath); sl@0: if (ret!=KErrNone) sl@0: return(ret); sl@0: } sl@0: else sl@0: { sl@0: // Client has submitted a single drive to monitor sl@0: monitorAllDrives=EFalse; sl@0: sl@0: ret = ParseNoWildSubstPtr1(aRequest, aRequest->Src()); sl@0: if (ret!=KErrNone) sl@0: return(ret); sl@0: } sl@0: aRequest->SetScratchValue(monitorAllDrives); sl@0: ret = PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsNotifyChangeEx, __PLATSEC_DIAGNOSTIC_STRING("Extended Change Notifier")); sl@0: return(ret); sl@0: } sl@0: sl@0: TInt TFsNotifyChangeCancel::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: FsNotify::CancelChangeSession(aRequest->Session()); sl@0: #if defined(_DEBUG) sl@0: FsNotify::CancelDebugSession(aRequest->Session()); sl@0: #endif sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: sl@0: TInt TFsNotifyChangeCancel::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: sl@0: TInt TFsNotifyChangeCancelEx::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: FsNotify::CancelChangeSession(aRequest->Session(),(TRequestStatus*)aRequest->Message().Ptr0()); sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: FsNotify::CancelDebugSession(aRequest->Session()); sl@0: #endif sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: sl@0: TInt TFsNotifyChangeCancelEx::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: // sl@0: // Setup a disk space notification request sl@0: // sl@0: TInt TFsNotifyDiskSpace::DoRequestL(CFsRequest *aRequest) sl@0: { sl@0: //-- first check that the threshold value is correct and is less than the volume size sl@0: const TUint64 threshold = aRequest->ScratchValue64(); sl@0: if(threshold <= 0) sl@0: return KErrArgument; sl@0: sl@0: //-- get the size of the mounted volume to check that the requested threshold isn't larger than the volume sl@0: TUint64 volSz; sl@0: TInt r = aRequest->Drive()->MountedVolumeSize(volSz); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: sl@0: if(threshold >= volSz) sl@0: return KErrArgument; sl@0: sl@0: sl@0: //-- Create the disk space notificator object and append it to the FsNotify queue sl@0: CDiskSpaceInfo* info=new CDiskSpaceInfo; sl@0: if(info==NULL) sl@0: return(KErrNoMemory); sl@0: sl@0: const RMessage2& m=aRequest->Message(); sl@0: info->Initialise((TRequestStatus*)m.Ptr2(),m,aRequest->Session(),threshold); sl@0: sl@0: r=FsNotify::AddDiskSpace(info,aRequest->DriveNumber()); sl@0: if(r!=KErrNone) sl@0: delete info; sl@0: sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: TInt TFsNotifyDiskSpace::Initialise(CFsRequest *aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: TInt r=ValidateDriveDoSubst(aRequest->Message().Int1(),aRequest); sl@0: if (r==KErrNone) sl@0: { sl@0: TInt64 threshold; sl@0: TPtr8 tBuf((TUint8*)&threshold,sizeof(TInt64)); sl@0: aRequest->ReadL(KMsgPtr0,tBuf); sl@0: aRequest->SetScratchValue64(threshold); sl@0: } sl@0: return(r); sl@0: } sl@0: sl@0: TInt TFsNotifyDiskSpaceCancel::DoRequestL(CFsRequest *aRequest) sl@0: // sl@0: // Cancel disk space notification sl@0: // sl@0: { sl@0: FsNotify::CancelDiskSpaceSession(aRequest->Session(),(TRequestStatus*)aRequest->Message().Ptr0()); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: TInt TFsNotifyDiskSpaceCancel::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsSynchroniseDriveThread::DoRequestL(CFsRequest* /*aRequest*/) sl@0: // sl@0: // This is to ensure that previous message has been handled in drive thread. sl@0: // sl@0: { sl@0: return CFsRequest::EReqActionComplete; sl@0: } sl@0: sl@0: TInt TFsSynchroniseDriveThread::Initialise(CFsRequest *aRequest) sl@0: // sl@0: // Set the drive thread. sl@0: // sl@0: { sl@0: if(aRequest->Message().Int0() == -1) //If no drive thread then complete the message sl@0: { sl@0: return CFsRequest::EReqActionComplete; sl@0: } sl@0: TInt r=ValidateDriveDoSubst(aRequest->Message().Int0(),aRequest); sl@0: return r; sl@0: } sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: EXPORT_C void DebugNotifySessions(TInt aFunction,TInt /*aDrive*/) sl@0: // sl@0: // Notify sessions of a debug event sl@0: // sl@0: { sl@0: // Notifying involves memory de-allocation on the file server's heap - sl@0: // check if we need to switch heaps. sl@0: RAllocator* current_alloc = &User::Heap(); sl@0: RAllocator* svr_alloc = ServerThreadAllocator; sl@0: if (current_alloc != svr_alloc) sl@0: User::SwitchHeap(svr_alloc); sl@0: FsNotify::HandleDebug(aFunction); sl@0: if (current_alloc != svr_alloc) sl@0: User::SwitchHeap(current_alloc); sl@0: } sl@0: #else sl@0: EXPORT_C void DebugNotifySessions(TInt,TInt) sl@0: // sl@0: // Notify sessions of a debug event sl@0: // sl@0: {} sl@0: #endif sl@0: sl@0: sl@0: TInt TFsDriveList::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get the current drive list. sl@0: // sl@0: { sl@0: TDriveList list(KMaxDrives); sl@0: sl@0: const TUint mask = (TUint) aRequest->Message().Int1(); sl@0: const TUint matchedFlags= mask & KDriveAttMatchedFlags; //KDriveAttMatchedFlags = 0xFFF sl@0: const TUint matchedAtt = mask & KDriveAttMatchedAtt; //KDriveAttMatchedAtt = 0x0FFF0000 sl@0: sl@0: TInt r = ValidateMatchMask(mask); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: for (TInt i=0;iWriteL(KMsgPtr0,list); sl@0: sl@0: // Finally, kick off a speculative probe for devices sl@0: ProxyDrives->Lock(); sl@0: TInt idx = ProxyDrives->Count(); sl@0: while(idx--) sl@0: { sl@0: CExtProxyDriveFactory* pF = (CExtProxyDriveFactory*)(*ProxyDrives)[idx]; sl@0: if(pF) sl@0: { sl@0: pF->AsyncEnumerate(); sl@0: } sl@0: } sl@0: ProxyDrives->Unlock(); sl@0: sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsDriveList::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsDrive::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get drive info. sl@0: // sl@0: { sl@0: // executed in main thread, therefore lock to ensure that sl@0: // dismount cannot occur during request sl@0: FsThreadManager::LockDrive(aRequest->DriveNumber()); sl@0: TDriveInfo info; sl@0: aRequest->Drive()->DriveInfo(info); sl@0: if(aRequest->SubstedDrive()) sl@0: info.iDriveAtt=KDriveAttSubsted; sl@0: FsThreadManager::UnlockDrive(aRequest->DriveNumber()); sl@0: TPckgC pInfo(info); sl@0: aRequest->WriteL(KMsgPtr0,pInfo); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsDrive::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: TInt r=ValidateDriveDoSubst(aRequest->Message().Int1(),aRequest); sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: /** sl@0: Get volume info. sl@0: */ sl@0: TInt TFsVolume::DoRequestL(CFsRequest* aRequest) sl@0: { sl@0: TVolumeInfo v; sl@0: TPckg pV(v); sl@0: sl@0: //-- read TVolumeInfo from the client side, the client may have provided some data to pass to the server and FSY side sl@0: aRequest->ReadL(KMsgPtr0,pV); sl@0: sl@0: TRequestStatus* pStat = (TRequestStatus*)aRequest->Message().Ptr2(); sl@0: if(pStat) sl@0: {//-- the user called an asynchronous version of the RFs::Volume sl@0: //-- indicate that we request free space asynchronously by setting a special flag that we will pass to the FSY sl@0: v.iVolSizeAsync = ETrue; sl@0: //-- at present the user's request will be completed by file server as the result of TFsVolume operation. sl@0: } sl@0: else sl@0: { sl@0: v.iVolSizeAsync = EFalse; sl@0: } sl@0: sl@0: //-- ask the FSY to provide us its volume information sl@0: TInt r=aRequest->Drive()->Volume(v); sl@0: sl@0: CSessionFs* session=aRequest->Session(); sl@0: if (r==KErrNone) sl@0: { sl@0: TDrive* drive = aRequest->Drive(); sl@0: const TInt driveNumber = drive->DriveNumber(); sl@0: sl@0: if(!session->ReservedAccess(driveNumber)) sl@0: { sl@0: const TInt reserve = drive->ReservedSpace(); sl@0: if(v.iFree <= reserve) sl@0: v.iFree = 0; sl@0: else sl@0: v.iFree -= reserve; sl@0: } sl@0: sl@0: if(aRequest->SubstedDrive()) sl@0: v.iDrive.iDriveAtt=KDriveAttSubsted; sl@0: sl@0: sl@0: sl@0: if (drive->IsMounted() && drive->CurrentMount().LocalBufferSupport() == KErrNone && CCacheManagerFactory::CacheManager() != NULL) sl@0: v.iFileCacheFlags = TFileCacheSettings::Flags(driveNumber); sl@0: else sl@0: v.iFileCacheFlags = TFileCacheFlags(0); sl@0: sl@0: sl@0: aRequest->WriteL(KMsgPtr0,pV); sl@0: } sl@0: sl@0: return(r); sl@0: } sl@0: sl@0: TInt TFsVolume::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: sl@0: TInt r=ValidateDriveDoSubst(aRequest->Message().Int1(),aRequest); sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: TInt TFsSetVolume::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Set the volume name. sl@0: // sl@0: { sl@0: TInt r = CheckDiskSpace(0, aRequest); sl@0: if(r != KErrNone) sl@0: return r; sl@0: sl@0: TFileName volumeName; sl@0: aRequest->ReadL(KMsgPtr0,volumeName); sl@0: if (volumeName.Length()>KMaxVolumeNameLength) // KMaxVolumeNameLength = 11 sl@0: return(KErrBadName); sl@0: sl@0: // Validate name - return KErrBadName if it contains illegal characters such as * ? / | > < sl@0: TNameChecker checker(volumeName); sl@0: TText badChar; sl@0: if (checker.IsIllegalName(badChar)) sl@0: return(KErrBadName); sl@0: sl@0: return(aRequest->Drive()->SetVolume(volumeName)); sl@0: } sl@0: sl@0: sl@0: TInt TFsSetVolume::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: TInt r=ValidateDriveDoSubst(aRequest->Message().Int1(),aRequest); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: if (!KCapFsSetVolume.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Set Volume"))) sl@0: return KErrPermissionDenied; sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt TFsSubst::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get a drive substitution. sl@0: // sl@0: { sl@0: TInt r=ValidateDrive(aRequest->Message().Int1(),aRequest); sl@0: if(r!=KErrNone) sl@0: return(r); sl@0: TFileName substName; sl@0: __PRINT(_L("aRequest->Drive()->Att()&KDriveAttSubsted")); sl@0: __PRINT1(_L("aRequest->Drive()->Subst()"),&aRequest->Drive()->Subst()); sl@0: if (aRequest->Drive()->IsSubsted()) sl@0: substName=aRequest->Drive()->Subst(); sl@0: aRequest->WriteL(KMsgPtr0,substName); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: TInt TFsSubst::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt TFsSetSubst::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Set a drive substitution. sl@0: // sl@0: { sl@0: TInt r=ValidateDrive(aRequest->Message().Int1(),aRequest); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: TDrive* pD=aRequest->Drive(); sl@0: r=ParsePathPtr0(aRequest,aRequest->Src()); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: //TODO: no protection for unsubsting drives (could check substed path if system then only CRoot process can unsubst sl@0: if (pD->IsSubsted() && !aRequest->Src().DrivePresent() && !aRequest->Src().PathPresent()) sl@0: { sl@0: delete &pD->Subst(); sl@0: pD->SetSubst(NULL); sl@0: pD->SetAtt(0); sl@0: pD->SetSubstedDrive(NULL); sl@0: return(KErrNone); sl@0: } sl@0: r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysSetSubst,&KCapFsPriSetSubst,&KCapFsROSetSubst, __PLATSEC_DIAGNOSTIC_STRING("Set Subst")); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: if (pD->Att()&(KDriveAttLocal|KDriveAttRom|KDriveAttRedirected|KDriveAttSubsted)) sl@0: return(KErrGeneral); sl@0: if (pD==aRequest->Drive()) sl@0: return(KErrGeneral); sl@0: if (aRequest->Drive()->Att()&(KDriveAttRedirected|KDriveAttSubsted)) sl@0: return(KErrInUse); sl@0: HBufC* pS=aRequest->Src().FullName().Alloc(); sl@0: if (pS==NULL) sl@0: return(KErrNoMemory); sl@0: __ASSERT_DEBUG(!&pD->SubstedDrive(),Fault(ETFsSetSubstNotNull)); sl@0: delete &pD->Subst(); sl@0: pD->SetSubst(pS); sl@0: pD->SetSubstedDrive(aRequest->Drive()); sl@0: pD->SetAtt(KDriveAttSubsted); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsSetSubst::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: if (!KCapFsSetSubst.CheckPolicy(aRequest->Message(),__PLATSEC_DIAGNOSTIC_STRING("Set subst"))) sl@0: return KErrPermissionDenied; sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt TFsRealName::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get the real name of a file. sl@0: // sl@0: { sl@0: TInt r=ParseSubstPtr0(aRequest,aRequest->Src()); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysRealName,&KCapFsPriRealName, __PLATSEC_DIAGNOSTIC_STRING("Real Name")); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: TFileName substName; sl@0: if (aRequest->Drive()->Att()&KDriveAttRedirected) sl@0: substName=aRequest->Drive()->Subst(); // DANGER? sl@0: else sl@0: substName=aRequest->Src().Drive(); sl@0: if ((substName.Length()+aRequest->Src().FullName().Mid(2).Length())>KMaxFileName) sl@0: return(KErrBadName); sl@0: substName+=aRequest->Src().FullName().Mid(2); sl@0: aRequest->WriteL(KMsgPtr1,substName); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsRealName::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsDefaultPath::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get the default path. sl@0: // sl@0: { sl@0: if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)) sl@0: return KErrNotSupported; sl@0: else if(PlatSec::ConfigSetting(PlatSec::EPlatSecDiagnotics)) sl@0: { sl@0: //FIXME: to be remove the following when platform is fully secure sl@0: RThread tT; sl@0: TInt r=aRequest->Message().Client(tT,EOwnerThread); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: RProcess tP; sl@0: r=tT.Process(tP); sl@0: if(r!=KErrNone) sl@0: { sl@0: tT.Close(); sl@0: return r; sl@0: } sl@0: TName n; sl@0: n=tP.Name(); sl@0: TInt b=n.Locate('['); sl@0: if (b>=0) sl@0: n.SetLength(b); sl@0: RDebug::Print(_L("**** API violation: %S should not use DefaultPath()\n"),&n); sl@0: tP.Close(); sl@0: tT.Close(); sl@0: //FIXME END sl@0: aRequest->WriteL(KMsgPtr0,TheDefaultPath); sl@0: return(KErrNone); sl@0: } sl@0: else sl@0: { sl@0: aRequest->WriteL(KMsgPtr0,TheDefaultPath); sl@0: return(KErrNone); sl@0: } sl@0: } sl@0: sl@0: TInt TFsDefaultPath::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsSetDefaultPath::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Set the default path. sl@0: // sl@0: { sl@0: if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)) sl@0: return KErrNotSupported; sl@0: else if(PlatSec::ConfigSetting(PlatSec::EPlatSecDiagnotics)) sl@0: { sl@0: //FIXME: to be remove the following when platform is fully secure sl@0: RThread tT; sl@0: TInt r=aRequest->Message().Client(tT,EOwnerThread); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: RProcess tP; sl@0: r=tT.Process(tP); sl@0: if(r!=KErrNone) sl@0: { sl@0: tT.Close(); sl@0: return r; sl@0: } sl@0: TName n; sl@0: n=tP.Name(); sl@0: TInt b=n.Locate('['); sl@0: if (b>=0) sl@0: n.SetLength(b); sl@0: RDebug::Print(_L("**** API violation: %S should not use SetDefaultPath()\n"),&n); sl@0: tP.Close(); sl@0: tT.Close(); sl@0: //FIXME END sl@0: TParse parse; sl@0: /*TInt*/ r=ParsePathPtr0(aRequest,parse); sl@0: if (r!=KErrNone && r!=KErrInUse) sl@0: return(r); sl@0: if (IsIllegalFullName(parse.FullName())) sl@0: return(KErrBadName); sl@0: TheDefaultPath=parse.FullName(); sl@0: return(KErrNone); sl@0: } sl@0: else sl@0: { sl@0: TParse parse; sl@0: TInt r=ParsePathPtr0(aRequest,parse); sl@0: if (r!=KErrNone && r!=KErrInUse) sl@0: return(r); sl@0: if (IsIllegalFullName(parse.FullName())) sl@0: return(KErrBadName); sl@0: TheDefaultPath=parse.FullName(); sl@0: return(KErrNone); sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt TFsSetDefaultPath::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsSessionPath::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get the session path sl@0: // sl@0: { sl@0: aRequest->WriteL(KMsgPtr0,aRequest->Session()->Path()); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsSessionPath::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt TFsSetSessionPath::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Set the session path sl@0: // sl@0: { sl@0: TParse parse; sl@0: TInt r=ParsePathPtr0(aRequest,parse); sl@0: if (r!=KErrNone && r!=KErrInUse) sl@0: return(r); sl@0: r=PathCheck(aRequest,parse.FullName().Mid(2),&KCapFsSysSetSessionPath,&KCapFsPriSetSessionPath, __PLATSEC_DIAGNOSTIC_STRING("Set Session Path")); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: if (IsIllegalFullName(parse.FullName())) sl@0: return(KErrBadName); sl@0: HBufC* pP=parse.FullName().Alloc(); sl@0: if (pP==NULL) sl@0: return(KErrNoMemory); sl@0: delete &aRequest->Session()->Path(); sl@0: aRequest->Session()->SetPath(pP); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TFsSetSessionPath::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: TInt TFsParse::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Parse a file name. sl@0: // sl@0: { sl@0: TFileName name; sl@0: aRequest->ReadL(KMsgPtr0,name); sl@0: TFileName rel; sl@0: if (aRequest->Message().Ptr1()!=NULL) sl@0: aRequest->ReadL(KMsgPtr1,rel); sl@0: TParse p; sl@0: TInt r=p.Set(name,&rel,&aRequest->Session()->Path()); sl@0: if (r==KErrNone) sl@0: { sl@0: TPckgC pP(p); sl@0: aRequest->WriteL(KMsgPtr2,pP); sl@0: } sl@0: return(r); sl@0: } sl@0: sl@0: TInt TFsParse::Initialise(CFsRequest* /*aRequest*/) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsReserveDriveSpace::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // set reserved value to add to a drives reserved area sl@0: // sl@0: { sl@0: // extract request info sl@0: CSessionFs* session=aRequest->Session(); sl@0: TDrive* drive = aRequest->Drive(); sl@0: sl@0: if(session->ReservedAccess(drive->DriveNumber())) sl@0: return KErrInUse; sl@0: sl@0: const TInt reserve = aRequest->Message().Int1(); //-- bytes to reserve on the drive sl@0: sl@0: // Check if requested reserve space is within the range sl@0: if(reserve > KMaxSessionDriveReserved || reserve < 0) sl@0: return KErrArgument; sl@0: sl@0: const TInt64 threshold = reserve + drive->ReservedSpace(); //-- free bytes on the volume we actually need sl@0: sl@0: TInt nRes = drive->RequestFreeSpaceOnMount(threshold); sl@0: if(nRes != KErrNone) sl@0: return nRes; sl@0: sl@0: const TInt current = session->Reserved(drive->DriveNumber()); sl@0: const TInt diff = reserve - current; sl@0: TInt drvReserved = drive->ReservedSpace(); sl@0: if((drvReserved + diff) > KMaxTotalDriveReserved) sl@0: return KErrTooBig; sl@0: sl@0: drvReserved += diff; sl@0: drive->SetReservedSpace(drvReserved); sl@0: return session->SetReserved(drive->DriveNumber(), reserve); sl@0: sl@0: } sl@0: sl@0: TInt TFsReserveDriveSpace::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // Validate drive and set up the session parameters for request sl@0: // sl@0: { sl@0: // if (!KCapFsReserveDriveSpace.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Reserve Drive Space"))) sl@0: // return KErrPermissionDenied; sl@0: TInt drvNumber=aRequest->Message().Int1(); sl@0: drvNumber=aRequest->Message().Int0(); sl@0: TInt r=ValidateDrive(aRequest->Message().Int0(),aRequest); sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: TInt TFsGetReserveAccess::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Get reserved access to a drives reserved area first checking that the session has first reserved some space sl@0: // sl@0: { sl@0: CSessionFs* session=aRequest->Session(); sl@0: sl@0: TInt size=session->Reserved(aRequest->Drive()->DriveNumber()); sl@0: if(size <= 0) sl@0: return KErrPermissionDenied; sl@0: else sl@0: session->SetReservedAccess(aRequest->Drive()->DriveNumber(),ETrue); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsGetReserveAccess::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: // if (!KCapFsGetReserveAccess.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Get Reserve Access"))) sl@0: // return KErrPermissionDenied; sl@0: TInt r=ValidateDrive(aRequest->Message().Int0(),aRequest); sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: TInt TFsReleaseReserveAccess::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Remove access for this session to the locked area for a given drive sl@0: // sl@0: { sl@0: aRequest->Session()->SetReservedAccess(aRequest->Drive()->DriveNumber(),EFalse); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsReleaseReserveAccess::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: // if (!KCapFsReleaseReserveAccess.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Release Reserve Access"))) sl@0: // return KErrPermissionDenied; sl@0: TInt r=ValidateDrive(aRequest->Message().Int0(),aRequest); sl@0: return(r); sl@0: } sl@0: sl@0: TInt TFsSetStartupConfiguration::DoRequestL(CFsRequest* aRequest) sl@0: // sl@0: // Configure file server according to command and parameters. sl@0: // sl@0: { sl@0: TInt cmd = aRequest->Message().Int0(); sl@0: sl@0: switch (cmd) sl@0: { sl@0: case ELoaderPriority: sl@0: // Set loader thread priority sl@0: { sl@0: TInt r; sl@0: TFullName loaderFullName(RProcess().FullName()); sl@0: loaderFullName.Append(_L("::LoaderThread")); sl@0: RThread loader; sl@0: r = loader.Open(loaderFullName); sl@0: if (r != KErrNone) sl@0: return r; sl@0: loader.SetPriority((TThreadPriority)aRequest->Message().Int1()); sl@0: loader.Close(); sl@0: } sl@0: break; sl@0: case ESetRugged: sl@0: { sl@0: TInt drive = aRequest->Message().Int1(); sl@0: TInt r = ValidateDrive(drive, aRequest); sl@0: if (r != KErrNone) sl@0: return r; sl@0: TInt value = aRequest->Message().Int2(); sl@0: aRequest->Drive()->SetRugged(value); sl@0: } sl@0: break; sl@0: default: sl@0: return KErrArgument; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsSetStartupConfiguration::Initialise(CFsRequest* aRequest) sl@0: // sl@0: // Check SID of message sender. Can be estart only sl@0: // sl@0: { sl@0: if (aRequest->Message().SecureId() != KEstartUidValue) sl@0: return KErrPermissionDenied; sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: const TInt KinitialChanges = EChangesLocale|EChangesMidnightCrossover|EChangesThreadDeath|EChangesPowerStatus|EChangesSystemTime|EChangesFreeMemory|EChangesOutOfMemory; sl@0: sl@0: CKernEventNotifier* CKernEventNotifier::New(TInt aPriority) sl@0: { sl@0: __PRINT(_L("CKernEventNotifier::New")); sl@0: CKernEventNotifier* self = new CKernEventNotifier(aPriority); sl@0: if (self && (self->iChangeNotifier.Create() != KErrNone)) sl@0: delete self, self = NULL; sl@0: return self; sl@0: } sl@0: sl@0: CKernEventNotifier::~CKernEventNotifier() sl@0: { sl@0: Cancel(); sl@0: iChangeNotifier.Close(); sl@0: } sl@0: sl@0: void CKernEventNotifier::Start() sl@0: { sl@0: SetActive(); sl@0: iChangeNotifier.Logon(iStatus); sl@0: } sl@0: sl@0: void CKernEventNotifier::RunL() sl@0: { sl@0: __PRINT(_L("CKernEventNotifier::RunL")); sl@0: iChange = iStatus.Int(); sl@0: Start(); sl@0: sl@0: /* Avoid being triggered by initial events */ sl@0: if (iChange != 0 && (iChange & KinitialChanges) != KinitialChanges) sl@0: { sl@0: if (iChange & EChangesLocale) sl@0: CKernEventNotifier::LocaleChangeCallback(); sl@0: if (iChange & EChangesFreeMemory) sl@0: CKernEventNotifier::FreeMemoryChangeCallback(); sl@0: // Add other event capture below this line sl@0: iChange = 0; sl@0: } sl@0: } sl@0: sl@0: void CKernEventNotifier::DoCancel() sl@0: { sl@0: iChangeNotifier.LogonCancel(); sl@0: } sl@0: sl@0: sl@0: extern TBool FatUtilitiesUpdateDrivesNotified; sl@0: extern TBool FatUtilityFunctionsSet; sl@0: sl@0: TInt CKernEventNotifier::LocaleChangeCallback(TAny*) sl@0: { sl@0: __PRINT(_L("CKernEventNotifier::LocaleChangeCallback")); sl@0: sl@0: //-- check if the locale has just been set and the drives are not yet notified about this. sl@0: if(FatUtilityFunctionsSet && !FatUtilitiesUpdateDrivesNotified) sl@0: {//-- notify drives about locale shange, but only once sl@0: for(TInt i=0; i=0 && drive.IsRemovable() && !drive.IsSubsted()) sl@0: { sl@0: __PRINT1(_L("CKernEventNotifier::LocaleChangeCallback upd drive: %d"), drive.DriveNumber()); sl@0: drive.SetChanged(ETrue); sl@0: } sl@0: } sl@0: sl@0: FatUtilitiesUpdateDrivesNotified = ETrue; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt TFsQueryVolumeInfoExt::DoRequestL(CFsRequest* aRequest) sl@0: { sl@0: const TInt cmd = aRequest->Message().Int1(); sl@0: TInt rel; sl@0: sl@0: TDrive* pDrive = aRequest->Drive(); sl@0: sl@0: rel = pDrive->CheckMount(); sl@0: if(rel != KErrNone) sl@0: return rel; sl@0: sl@0: switch (cmd) sl@0: { sl@0: sl@0: //------------------------------------------------- sl@0: //-- file system sub type query sl@0: case EFileSystemSubType: sl@0: { sl@0: TFSName name; sl@0: if (pDrive->IsMounted()) sl@0: { sl@0: rel = pDrive->CurrentMount().FileSystemSubType(name); sl@0: sl@0: //-- get the Mount's file system name if the FS subtype query is not supported or there are no subtypes. sl@0: if (rel==KErrNotSupported) sl@0: { sl@0: pDrive->CurrentMount().FileSystemName(name); sl@0: } sl@0: sl@0: if (name.Length()) sl@0: { sl@0: TPckgBuf pckgBuf(name); sl@0: aRequest->WriteL(KMsgPtr2, pckgBuf); sl@0: return KErrNone; sl@0: } sl@0: else sl@0: { sl@0: return rel; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: return KErrNotReady; sl@0: } sl@0: } sl@0: sl@0: sl@0: //------------------------------------------------- sl@0: //-- this is RFs::VolumeIOParam() query sl@0: case EIOParamInfo: sl@0: { sl@0: TVolumeIOParamInfo ioInfo; sl@0: // 1. gets block size information via media driver sl@0: const TInt drive = aRequest->Message().Int0(); sl@0: sl@0: // validates local drive numbers sl@0: if(!IsValidLocalDriveMapping(drive)) sl@0: { sl@0: ioInfo.iBlockSize = KErrNotReady; sl@0: } sl@0: else sl@0: { sl@0: // Get media capability sl@0: TLocalDriveCapsV6Buf capsBuf; sl@0: sl@0: // is the drive local? sl@0: if (!IsProxyDrive(drive)) sl@0: { sl@0: // if not valid local drive, use default values in localDriveCaps sl@0: // if valid local drive and not locked, use TBusLocalDrive::Caps() values sl@0: // if valid drive and locked, hard-code attributes sl@0: rel = GetLocalDrive(drive).Caps(capsBuf); sl@0: } sl@0: else // this need to be made a bit nicer sl@0: { sl@0: CExtProxyDrive* pD = GetProxyDrive(drive); sl@0: if(pD) sl@0: rel = pD->Caps(capsBuf); sl@0: else sl@0: rel = KErrNotReady; sl@0: } sl@0: sl@0: if (rel != KErrNone) sl@0: { sl@0: ioInfo.iBlockSize = rel; sl@0: } sl@0: else sl@0: { sl@0: TLocalDriveCapsV6& caps = capsBuf(); sl@0: if (caps.iBlockSize) sl@0: { sl@0: ioInfo.iBlockSize = caps.iBlockSize; sl@0: } sl@0: // returns default size (512) when block is not supported by sl@0: // underlying media sl@0: else sl@0: { sl@0: ioInfo.iBlockSize = KDefaultVolumeBlockSize; sl@0: } sl@0: } sl@0: } sl@0: sl@0: // 2. gets cluster size via mounted file system; Also get Max. file size supported by the file system sl@0: sl@0: ioInfo.iMaxSupportedFileSize = KMaxTUint64; //-- the value for "not supported case" sl@0: sl@0: if (pDrive->IsMounted()) sl@0: { sl@0: rel = pDrive->CurrentMount().FileSystemClusterSize(); sl@0: ioInfo.iClusterSize = rel; // return cluster size or an error code if error happened. sl@0: sl@0: pDrive->CurrentMount().GetMaxSupportedFileSize(ioInfo.iMaxSupportedFileSize); sl@0: sl@0: } sl@0: else sl@0: { sl@0: ioInfo.iClusterSize = KErrNotReady; sl@0: } sl@0: sl@0: // 3. get rec buffer size from estart.txt file sl@0: { sl@0: _LIT8(KLitSectionNameDrive,"Drive%C"); sl@0: ioInfo.iRecReadBufSize = KErrNotSupported; sl@0: ioInfo.iRecWriteBufSize = KErrNotSupported; sl@0: sl@0: TBuf8<8> sectionName; sl@0: TInt32 bufSize; sl@0: sectionName.Format(KLitSectionNameDrive, 'A' + drive); sl@0: // retrieve recommended buffer size information through F32 INI section sl@0: if (F32Properties::GetInt(sectionName, _L8("RecReadBufSize"), bufSize)) sl@0: { sl@0: ioInfo.iRecReadBufSize = bufSize; sl@0: } sl@0: if (F32Properties::GetInt(sectionName, _L8("RecWriteBufSize"), bufSize)) sl@0: { sl@0: ioInfo.iRecWriteBufSize = bufSize; sl@0: } sl@0: sl@0: // packaging and returning results sl@0: TPckgBuf pckgBuf(ioInfo); sl@0: aRequest->WriteL(KMsgPtr2, pckgBuf); sl@0: } sl@0: sl@0: // always return KErrNone as error codes are packaged and returned via ioInfo members sl@0: return KErrNone; sl@0: } //case EIOParamInfo: sl@0: sl@0: //------------------------------------------------- sl@0: //-- check if the specified drive is synchronous or not sl@0: case EIsDriveSync: sl@0: { sl@0: const TInt drive = aRequest->Message().Int0(); sl@0: const TBool bDrvSynch = FsThreadManager::IsDriveSync(drive, EFalse); sl@0: TPckgBuf buf(bDrvSynch); sl@0: aRequest->WriteL(KMsgPtr2, buf); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: //------------------------------------------------- sl@0: //-- query if the drive is finalised sl@0: case EIsDriveFinalised: sl@0: { sl@0: TBool bFinalised; sl@0: TInt nRes = pDrive->CurrentMount().IsMountFinalised(bFinalised); sl@0: if(nRes != KErrNone) sl@0: return nRes; sl@0: sl@0: TPckgBuf buf(bFinalised); sl@0: aRequest->WriteL(KMsgPtr2, buf); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: default: sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: } sl@0: } sl@0: sl@0: TInt TFsQueryVolumeInfoExt::Initialise(CFsRequest* aRequest) sl@0: { sl@0: TInt r = ValidateDriveDoSubst(aRequest->Message().Int0(),aRequest); sl@0: return r; sl@0: } sl@0: sl@0: TInt CKernEventNotifier::FreeMemoryChangeCallback() sl@0: { sl@0: __PRINT(_L("CKernEventNotifier::FreeMemoryChangeCallback")); sl@0: sl@0: TBool belowThreshold = (iChange & EChangesLowMemory)?(TBool)ETrue:(TBool)EFalse; sl@0: CCacheManager* manager = CCacheManagerFactory::CacheManager(); sl@0: if (manager) sl@0: { sl@0: manager->FreeMemoryChanged(belowThreshold); sl@0: sl@0: // start flushing all dirty data sl@0: if (belowThreshold) sl@0: { sl@0: Files->Lock(); sl@0: TInt count=Files->Count(); sl@0: while(count--) sl@0: { sl@0: CFileCB* file = (CFileCB*)(*Files)[count]; sl@0: if (file->FileCache()) sl@0: // Cannot report errors here sl@0: // coverity [unchecked_value] sl@0: (void)file->FileCache()->FlushDirty(); sl@0: } sl@0: Files->Unlock(); sl@0: } sl@0: } sl@0: sl@0: #ifdef SYMBIAN_ENABLE_FAT_DIRECTORY_OPT sl@0: CCacheMemoryManager* cacheMemManager = CCacheMemoryManagerFactory::CacheMemoryManager(); sl@0: if (cacheMemManager) sl@0: cacheMemManager->FreeMemoryChanged(belowThreshold); sl@0: #endif //#ifdef SYMBIAN_ENABLE_FAT_DIRECTORY_OPT sl@0: sl@0: return KErrNone; sl@0: } sl@0: