os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_notifier.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_notifier.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1294 @@
     1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// f32\sfile\sf_notifier.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "sf_notifier.h"
    1.22 +#include "sf_file_cache.h"
    1.23 +
    1.24 +CFsObjectCon* FsNotificationManager::iNotifyRequests = NULL;
    1.25 +RFastLock FsNotificationManager::iChainLock;
    1.26 +TInt FsNotificationManager::iFilterRegister[];
    1.27 +CFsPool<CFsNotificationBlock>* FsNotificationManager::iPool;
    1.28 +
    1.29 +
    1.30 +CFsNotificationPathFilter* CFsNotificationPathFilter::NewL(const TDesC& aPath, const TDesC& aFilename)
    1.31 +	{
    1.32 +	CFsNotificationPathFilter* self = new (ELeave) CFsNotificationPathFilter();
    1.33 +	CleanupStack::PushL(self);
    1.34 +	self->ConstructL(aPath,aFilename);
    1.35 +	CleanupStack::Pop(self);
    1.36 +	return self;
    1.37 +	}
    1.38 +
    1.39 +void CFsNotificationPathFilter::ConstructL(const TDesC& aPath, const TDesC& aFilename)
    1.40 +	{
    1.41 +	//Allocate the path and filename
    1.42 +	iPath = aPath.AllocL();
    1.43 +	iFilename = aFilename.AllocL();	
    1.44 +	}
    1.45 +
    1.46 +CFsNotificationPathFilter::~CFsNotificationPathFilter()
    1.47 +	{
    1.48 +	if(iFilename)
    1.49 +		delete iFilename;
    1.50 +	if(iPath)
    1.51 +		delete iPath;
    1.52 +	}
    1.53 +
    1.54 +CFsNotificationPathFilter::CFsNotificationPathFilter()
    1.55 +: iPath(NULL), iFilename(NULL)
    1.56 +	{
    1.57 +	}
    1.58 +
    1.59 +CFsNotifyRequest* CFsNotifyRequest::NewL()
    1.60 +	{
    1.61 +	CFsNotifyRequest* self = new(ELeave) CFsNotifyRequest();
    1.62 +	CleanupStack::PushL(self);
    1.63 +	self->ConstructL();
    1.64 +	CleanupStack::Pop();
    1.65 +	return self;
    1.66 +	}
    1.67 +
    1.68 +void CFsNotifyRequest::ConstructL()
    1.69 +	{
    1.70 +	User::LeaveIfError(iClientSyncLock.CreateLocal());
    1.71 +	User::LeaveIfError(iTailSemaphore.CreateLocal()); 
    1.72 +	}
    1.73 +
    1.74 +CFsNotifyRequest::CFsNotifyRequest()
    1.75 +	{
    1.76 +	SetActive(EInactive);
    1.77 +	}
    1.78 +
    1.79 +CFsNotifyRequest::~CFsNotifyRequest()
    1.80 +	{
    1.81 +	__PRINT(_L("CFsNotifyRequest::~CFsNotifyRequest()"));
    1.82 +	
    1.83 +	RemoveFilters();
    1.84 +	
    1.85 +	if(ClientMsgHandle()!=0)
    1.86 +		iClientMsg.Complete(KErrCancel);
    1.87 +	
    1.88 +	if(iBufferMsg.Handle()!=0)
    1.89 +		iBufferMsg.Complete(KErrCancel);
    1.90 +	
    1.91 +	iClientSyncLock.Close();
    1.92 +	iTailSemaphore.Close();
    1.93 +	}
    1.94 +
    1.95 +/*
    1.96 + * Returns the Array of TypeFilters.
    1.97 + * Each TFsNotificationTypeFilter matches to a particular TFsNotification::TFsNotificationType
    1.98 + * and has a CFsNotificationFilter which stores the iPath and iName associated with this filter type.
    1.99 + * 
   1.100 + * (These are speerated so that we can have multiple type filters for every name filter)
   1.101 + */
   1.102 +TFsNotificationTypeArray* CFsNotifyRequest::FilterTypeList(TInt aDrive,TInt aIndex)
   1.103 +	{
   1.104 +	__ASSERT_DEBUG(aIndex < KNumRegisterableFilters,Fault(ENotificationFault));
   1.105 +
   1.106 +	TFsNotificationTypeDriveArray* filters = iDrivesTypesFiltersMap.Find(aDrive);
   1.107 +	if(filters)
   1.108 +		return &((*filters)[aIndex]);
   1.109 +	else
   1.110 +		return NULL;
   1.111 +	}
   1.112 +
   1.113 +//Sets filter's notification request status
   1.114 +void CFsNotifyRequest::SetActive(TNotifyRequestStatus aValue)
   1.115 +	{
   1.116 +	iNotifyRequestStatus = aValue;
   1.117 +	}
   1.118 +
   1.119 +CFsNotifyRequest::TNotifyRequestStatus CFsNotifyRequest::ActiveStatus()
   1.120 +	{
   1.121 +	return (TNotifyRequestStatus)iNotifyRequestStatus;
   1.122 +	}
   1.123 +
   1.124 +//Completes and frees notification request
   1.125 +//In case of KErrNone must be called with iChainLock already held
   1.126 +void CFsNotifyRequest::CompleteClientRequest(TInt aReason,TBool aIsCancel)
   1.127 +	{
   1.128 +	__PRINT(_L("CFsNotifyRequest::CompleteClientRequest()"));
   1.129 +
   1.130 +	iClientSyncLock.Wait();
   1.131 +	
   1.132 +	if(aReason==KErrNone) 
   1.133 +		{
   1.134 +		__PRINT(_L("CFsNotifyRequest::CompleteClientRequest() - Complete KErrNone"));
   1.135 +		//Synchronising the current iServerTail to the client.
   1.136 +		iClientHead = iClientTail; //Client has read all previous entries
   1.137 +		iClientTail = iServerTail; //Client's new tail is everything the server has been writing since this function was last called
   1.138 +		TInt clientTail = iClientTail;
   1.139 +		TPckg<TInt> tailDes(clientTail);
   1.140 +		iClientMsg.Write(KMsgPtr0,tailDes);
   1.141 +		}
   1.142 +	else if(aIsCancel)
   1.143 +		{
   1.144 +		__PRINT(_L("CFsNotifyRequest::CompleteClientRequest() - Complete isCancel"));
   1.145 +		iServerTail = 0;
   1.146 +		iClientTail = 0;
   1.147 +		iClientHead = 0;
   1.148 +		TPckgBuf<TInt> tailDes(iClientTail);
   1.149 +		//Perhaps client has crashed so no point checking return:
   1.150 +		iClientMsg.Write(KMsgPtr0,tailDes); 
   1.151 +		}
   1.152 +	__PRINT(_L("CFsNotifyRequest::CompleteClientRequest() - Complete Request"));
   1.153 +	iClientMsg.Complete(aReason);
   1.154 +	iClientSyncLock.Signal();
   1.155 +	}
   1.156 +	
   1.157 +TInt CFsNotifyRequest::SynchroniseBuffer(CFsNotificationBlock& aBlock,TInt aServerTail, TInt aNotificationSize)
   1.158 +	{
   1.159 +	TPtrC8 blockDes((TText8*)aBlock.Data(),aNotificationSize);
   1.160 +	return iBufferMsg.Write(KMsgPtr0,blockDes,aServerTail);
   1.161 +	}
   1.162 +
   1.163 +//Removes all filters.
   1.164 +//Deletes iPath, iFilename
   1.165 +TInt CFsNotifyRequest::RemoveFilters()
   1.166 +	{
   1.167 +	__PRINT(_L("CFsNotifyRequest::RemoveFilters()"));
   1.168 +		
   1.169 +	//For every drive with filters set...
   1.170 +	RHashMap<TInt,TFsNotificationTypeDriveArray>::TIter iterator(iDrivesTypesFiltersMap);
   1.171 +	TFsNotificationTypeDriveArray* currentDriveFilters = (TFsNotificationTypeDriveArray*)iterator.NextValue();
   1.172 +	while(currentDriveFilters)
   1.173 +		{
   1.174 +		//For every filter array (1 for each type of TFsNotificationType)
   1.175 +		for(TInt filterType = 0; filterType < KNumRegisterableFilters; filterType++)
   1.176 +			{
   1.177 +			TFsNotificationTypeArray& filterList = (*currentDriveFilters)[filterType];
   1.178 +			TInt filterTypeCount = filterList.Count();
   1.179 +			if(filterTypeCount)
   1.180 +				{
   1.181 +				//Remove this type from the filter register
   1.182 +				TFsNotification::TFsNotificationType type = FsNotificationHelper::NotificationType(filterType);
   1.183 +				FsNotificationManager::SetFilterRegister(type,EFalse,filterTypeCount);
   1.184 +				}
   1.185 +			filterList.Reset();
   1.186 +			filterList.Close();
   1.187 +			}
   1.188 +		currentDriveFilters->Reset();
   1.189 +		currentDriveFilters->Close();
   1.190 +		iterator.RemoveCurrent();
   1.191 +		currentDriveFilters = (TFsNotificationTypeDriveArray*)iterator.NextValue();
   1.192 +		}
   1.193 +	iDrivesTypesFiltersMap.Close();
   1.194 +	iPathFilterList.ResetAndDestroy();
   1.195 +	iPathFilterList.Close();
   1.196 +	return KErrNone;
   1.197 +	}
   1.198 +
   1.199 +TInt CFsNotifyRequest::AddFilterL(CFsNotificationPathFilter* aFilter, TUint aMask)
   1.200 +	{
   1.201 +	__PRINT(_L("CFsNotifyRequest::AddFilterL"));
   1.202 +
   1.203 +	iPathFilterList.AppendL(aFilter);
   1.204 +	
   1.205 +	//Get the drive number to so know which drive array to add the filter(s) to.
   1.206 +	TInt driveNum = FsNotificationHelper::DriveNumber(aFilter->iPath->Des()); 
   1.207 +	
   1.208 +	TInt notifyType = 1; 
   1.209 +	TInt r = KErrNone;
   1.210 +	//Create/Add a TypeFilter for each type in aMask
   1.211 +	while((notifyType & KNotificationValidFiltersMask) && (aMask & KNotificationValidFiltersMask))
   1.212 +		{
   1.213 +		//If this notifyType is present in aMask
   1.214 +		if(aMask & notifyType)
   1.215 +			{
   1.216 +			TFsNotificationTypeFilter typeFilter;
   1.217 +			typeFilter.iNotificationType = (TFsNotification::TFsNotificationType) notifyType;
   1.218 +			typeFilter.iPathFilter = aFilter;
   1.219 +			TInt index = FsNotificationHelper::TypeToIndex(typeFilter.iNotificationType);
   1.220 +			
   1.221 +			//If the per-drive-filterLists have not
   1.222 +			//been set up yet then do so now.
   1.223 +			TFsNotificationTypeDriveArray* driveArray = iDrivesTypesFiltersMap.Find(driveNum);
   1.224 +			if(!driveArray)
   1.225 +				{
   1.226 +				TFsNotificationTypeDriveArray dArray;
   1.227 +				r = iDrivesTypesFiltersMap.Insert(driveNum,dArray);
   1.228 +				User::LeaveIfError(r);					
   1.229 +				driveArray = iDrivesTypesFiltersMap.Find(driveNum);
   1.230 +				
   1.231 +				//Create filter arrays for every type
   1.232 +				for(TInt i =0; i< KNumRegisterableFilters; i++)
   1.233 +					{
   1.234 +					TFsNotificationTypeArray filterArray;
   1.235 +					driveArray->Append(filterArray);
   1.236 +					}
   1.237 +				}
   1.238 +			TFsNotificationTypeArray& filterArray= (*driveArray)[index];
   1.239 +			filterArray.Append(typeFilter);
   1.240 +
   1.241 +			//Remove this type from our mask
   1.242 +			//and continue
   1.243 +			aMask ^= notifyType;
   1.244 +			}
   1.245 +		notifyType <<= 1;
   1.246 +		}
   1.247 +	return r;
   1.248 +	}
   1.249 +
   1.250 +TInt CFsNotifyRequest::SetClientMessage(const RMessage2& aClientMsg)
   1.251 +	{
   1.252 +	__PRINT(_L("CFsNotifyRequest::SetClientMessage"));
   1.253 +	iClientMsg = aClientMsg;
   1.254 +	return KErrNone;
   1.255 +	}
   1.256 +
   1.257 +TInt CFsNotifyRequest::ClientMsgHandle()
   1.258 +	{
   1.259 +	return iClientMsg.Handle();
   1.260 +	}
   1.261 +
   1.262 +void CFsNotifyRequest::CloseNotification()
   1.263 +	{
   1.264 +	__PRINT(_L("CFsNotifyRequest::CloseNotification()"));
   1.265 +	iBufferMsg.Complete(KErrNone);
   1.266 +	if(ClientMsgHandle()!=0)
   1.267 +		CompleteClientRequest(KErrCancel,EFalse);
   1.268 +	}
   1.269 +
   1.270 +//New notification request from client
   1.271 +void FsNotificationManager::AddNotificationRequestL(CFsNotifyRequest* aNotificationRequest)
   1.272 +	{
   1.273 +	__PRINT(_L("FsNotificationManager::AddNotificationRequestL"));
   1.274 +	Lock();
   1.275 +	iNotifyRequests->AddL(aNotificationRequest,ETrue);
   1.276 +	Unlock();
   1.277 +	}
   1.278 +
   1.279 +//Notification request cancelled
   1.280 +//Must be called with iChainLock held
   1.281 +void FsNotificationManager::RemoveNotificationRequest(CFsNotifyRequest* aNotificationRequest)
   1.282 +	{
   1.283 +	__PRINT(_L("FsNotificationManager::RemoveNotificationRequest"));
   1.284 +	iNotifyRequests->Remove(aNotificationRequest,ETrue);
   1.285 +	}
   1.286 +
   1.287 +void FsNotificationManager::RemoveNotificationRequest(CSessionFs* aSession)
   1.288 +	{
   1.289 +	__PRINT(_L("FsNotificationManager::RemoveNotificationRequest(CSessionFs*)"));
   1.290 +	
   1.291 +	TInt count = Count();
   1.292 +	if(count)
   1.293 +		{
   1.294 +		Lock();
   1.295 +		count = Count(); //check again just incase it's changed before we got the lock
   1.296 +		if(count)
   1.297 +			{
   1.298 +			for(TInt i=0; i < count; i++)
   1.299 +				{
   1.300 +				//Remove all notification requests associated with this session.
   1.301 +				CFsNotifyRequest* notify = (CFsNotifyRequest*)(*iNotifyRequests)[i];
   1.302 +				if(notify->iSession == aSession)
   1.303 +					{
   1.304 +					RemoveNotificationRequest(notify);
   1.305 +					delete notify;
   1.306 +					}
   1.307 +				}
   1.308 +			if(!Count())
   1.309 +				{
   1.310 +				__PRINT(_L("FsNotificationManager::RemoveNotificationRequest(CSessionFs*) - Closing Manager"));
   1.311 +				Close();
   1.312 +				}
   1.313 +			}
   1.314 +		Unlock();
   1.315 +		}
   1.316 +	}
   1.317 +
   1.318 +TBool FsNotificationManager::IsInitialised()
   1.319 +	{
   1.320 +	__PRINT(_L("FsNotificationManager::IsInitialised()"));
   1.321 +	return (TBool)iNotifyRequests;
   1.322 +	}
   1.323 +
   1.324 +void FsNotificationManager::OpenL()
   1.325 +	{
   1.326 +	__PRINT(_L("FsNotificationManager::InitialiseL()"));
   1.327 +	if(!iNotifyRequests)
   1.328 +		{
   1.329 +		if(iChainLock.Handle() == 0)
   1.330 +			{
   1.331 +			User::LeaveIfError(iChainLock.CreateLocal());	
   1.332 +			}
   1.333 +		iNotifyRequests = TheContainer->CreateL();
   1.334 +		iPool = CFsPool<CFsNotificationBlock>::New(KNotificationPoolSize);
   1.335 +		User::LeaveIfNull(iPool);
   1.336 +		}
   1.337 +	}
   1.338 +
   1.339 +void FsNotificationManager::SetFilterRegister(TUint aFilter, TBool aAdd, TInt aCount)
   1.340 +	{
   1.341 +	__PRINT2(_L("FsNotificationManager::SetFilterRegister(aFilter=%u,aAdd=%d)"),aFilter,aAdd);
   1.342 +	TInt index = FsNotificationHelper::TypeToIndex((TFsNotification::TFsNotificationType)aFilter);
   1.343 +	TInt& fr = FsNotificationManager::FilterRegister(index);
   1.344 +	__ASSERT_DEBUG((aAdd) ? fr >= 0 : fr > 0,Fault(ENotificationFault));
   1.345 +	fr+= aAdd ? aCount : -aCount; 
   1.346 +	}
   1.347 +
   1.348 +void FsNotificationManager::SetFilterRegisterMask(TUint aMask,TBool aAdd)
   1.349 +	{
   1.350 +	__PRINT(_L("FsNotificationManager::RegisterFilterMask()"));
   1.351 +	TInt notifyType = 1; 
   1.352 +
   1.353 +	while(notifyType & KNotificationValidFiltersMask && aMask & KNotificationValidFiltersMask)
   1.354 +		{
   1.355 +		if(aMask & notifyType)
   1.356 +			{
   1.357 +			SetFilterRegister(notifyType,aAdd);
   1.358 +			aMask ^= notifyType;
   1.359 +			}
   1.360 +		notifyType <<= 1;
   1.361 +		}
   1.362 +	}
   1.363 +
   1.364 +TInt& FsNotificationManager::FilterRegister(TInt aIndex)
   1.365 +	{
   1.366 +	__PRINT(_L("FsNotificationManager::FilterRegister()"));
   1.367 +	__ASSERT_DEBUG(aIndex < KNumRegisterableFilters,Fault(ENotificationFault));
   1.368 +	return iFilterRegister[aIndex];
   1.369 +	}
   1.370 +
   1.371 +//Must be called with the iChainLock
   1.372 +void FsNotificationManager::Close()
   1.373 +	{
   1.374 +	__PRINT(_L("FsNotificationManager::Stop()"));
   1.375 +	CFsObjectCon*& request = iNotifyRequests;
   1.376 +	if(request)
   1.377 +		{
   1.378 +		TheContainer->Delete(request);
   1.379 +		delete iPool;
   1.380 +		iPool = NULL;
   1.381 +		}
   1.382 +	request = NULL;
   1.383 +	}
   1.384 +
   1.385 +TInt FsNotificationManager::Count()
   1.386 +	{
   1.387 +	__PRINT(_L("FsNotificationManager::Count()"));
   1.388 +	if(IsInitialised())
   1.389 +		return iNotifyRequests->Count();
   1.390 +	return 0;
   1.391 +	}
   1.392 +
   1.393 +void FsNotificationManager::Lock()
   1.394 +	{
   1.395 +	__PRINT(_L("--->FsNotificationManager::Lock()"));
   1.396 +	iChainLock.Wait();
   1.397 +	}
   1.398 +
   1.399 +void FsNotificationManager::Unlock()
   1.400 +	{
   1.401 +	__PRINT(_L("<---FsNotificationManager::Unlock()"));
   1.402 +	iChainLock.Signal();
   1.403 +	}
   1.404 +
   1.405 +//Get the notification type based on the TFsMessage function
   1.406 +void FsNotificationHelper::NotificationType(TInt aFunction,TFsNotification::TFsNotificationType& aNotificationType)
   1.407 +	{
   1.408 +	__PRINT(_L("FsNotificationHelper::NotificationType"));
   1.409 +	switch(aFunction)
   1.410 +		{
   1.411 +		case EFsFileWrite:
   1.412 +		case EFsFileWriteDirty:
   1.413 +		case EFsFileSetSize:
   1.414 +			{
   1.415 +			aNotificationType = TFsNotification::EFileChange;
   1.416 +			break;
   1.417 +			}
   1.418 +		case EFsRename:
   1.419 +		case EFsFileRename:
   1.420 +		case EFsReplace:
   1.421 +			{
   1.422 +			aNotificationType = TFsNotification::ERename;
   1.423 +			break;
   1.424 +			}
   1.425 +		case EFsMkDir:
   1.426 +		case EFsFileCreate:
   1.427 +		case EFsFileReplace:
   1.428 +			{
   1.429 +			aNotificationType = TFsNotification::ECreate;
   1.430 +			break;
   1.431 +			}
   1.432 +		case EFsFileSetAtt:
   1.433 +		case EFsFileSet:
   1.434 +		case EFsSetEntry:
   1.435 +			{
   1.436 +			aNotificationType = TFsNotification::EAttribute;
   1.437 +			break;
   1.438 +			}
   1.439 +		case EFsDelete:
   1.440 +		case EFsRmDir:
   1.441 +			{
   1.442 +			aNotificationType = TFsNotification::EDelete;
   1.443 +			break;
   1.444 +			}
   1.445 +		case EFsSetVolume:
   1.446 +			{
   1.447 +			aNotificationType = TFsNotification::EVolumeName;
   1.448 +			break;
   1.449 +			}
   1.450 +		case EFsSetDriveName:
   1.451 +			{
   1.452 +			aNotificationType = TFsNotification::EDriveName;
   1.453 +			break;
   1.454 +			}
   1.455 +		case EFsDismountFileSystem:
   1.456 +		case EFsMountFileSystem:
   1.457 +		case EFsFormatNext:
   1.458 +		case EFsRawDiskWrite:
   1.459 +		case EFsMountFileSystemScan:
   1.460 +			{
   1.461 +			aNotificationType = TFsNotification::EMediaChange;
   1.462 +			break;
   1.463 +			}
   1.464 +		default:
   1.465 +			{
   1.466 +			aNotificationType = (TFsNotification::TFsNotificationType)0;
   1.467 +			break;
   1.468 +			}
   1.469 +		}
   1.470 +	}
   1.471 +
   1.472 +//=====CFsNotificationBlock============================
   1.473 +// Uses CFsPool
   1.474 +
   1.475 +CFsNotificationBlock* CFsNotificationBlock::New()
   1.476 +	{
   1.477 +	return new CFsNotificationBlock();
   1.478 +	}
   1.479 +CFsNotificationBlock::CFsNotificationBlock()
   1.480 +	{
   1.481 +	}
   1.482 +CFsNotificationBlock::~CFsNotificationBlock()
   1.483 +	{
   1.484 +	//Nothing to do here
   1.485 +	}
   1.486 +TAny* CFsNotificationBlock::Data()
   1.487 +	{
   1.488 +	return (TAny*)&iData;
   1.489 +	}
   1.490 +
   1.491 +
   1.492 +//=====FsNotificationManager===========================
   1.493 + 
   1.494 +//Get the path of the file, folder or drive name based on the TFsMessage function
   1.495 +void FsNotificationHelper::PathName(CFsClientMessageRequest& aRequest, TDes& aPath)
   1.496 +	{
   1.497 +	__PRINT(_L("FsNotificationHelper::PathName"));
   1.498 +	//Get the notification type
   1.499 +	TInt function = aRequest.Operation()->Function();
   1.500 +	
   1.501 +	//Get the filename(s)
   1.502 +	switch(function)
   1.503 +		{
   1.504 +		case EFsFileWrite:			//EParseSrc | EFileShare
   1.505 +		case EFsFileSetSize:		//EParseSrc | EFileShare
   1.506 +		case EFsFileSetAtt:			//EParseDst | EParseSrc, - should not use these; has share.
   1.507 +		case EFsFileSet:
   1.508 +		case EFsFileWriteDirty:		//EFileShare
   1.509 +			{
   1.510 +			CFileShare* share = NULL;
   1.511 +			CFileCB* file = NULL;
   1.512 +			GetFileFromScratch(&aRequest,share,file);	
   1.513 +			aPath.Append(file->DriveNumber() + 'A');
   1.514 +			aPath.Append(':');
   1.515 +			aPath.Append(file->FileName().Des());
   1.516 +			break;
   1.517 +			}
   1.518 +		case EFsFileCreate:			//EParseSrc
   1.519 +		case EFsDelete:				//EParseSrc
   1.520 +		case EFsSetEntry:			//EParseSrc,
   1.521 +		case EFsFileRename:			//EParseDst | EParseSrc,
   1.522 +		case EFsRename:				//EParseDst | EParseSrc,
   1.523 +		case EFsReplace:			//EParseDst | EParseSrc,
   1.524 +		case EFsFileReplace:		//EParseSrc
   1.525 +			{
   1.526 +			aPath.Copy(aRequest.Src().FullName());
   1.527 +			break;
   1.528 +			}
   1.529 +        case EFsRmDir:              //EParseSrc
   1.530 +        case EFsMkDir:              //EParseSrc
   1.531 +            {
   1.532 +            aPath.Copy(aRequest.Src().DriveAndPath());
   1.533 +            break;
   1.534 +            }
   1.535 +		case EFsFormatNext:			//EParseSrc
   1.536 +		case EFsDismountFileSystem: //0
   1.537 +		case EFsMountFileSystem:	//0
   1.538 +		case EFsSetVolume:			//0
   1.539 +		case EFsSetDriveName:		//ESync
   1.540 +		case EFsRawDiskWrite:		//EParseSrc
   1.541 +		case EFsMountFileSystemScan:
   1.542 +			{
   1.543 +			_LIT(KFormatDrive,"?:");
   1.544 +			TBuf<2> drive;
   1.545 +			drive.Append(KFormatDrive);
   1.546 +			drive[0] = TText(aRequest.Drive()->DriveNumber() + 'A');
   1.547 +			aPath.Copy(drive);
   1.548 +			break;
   1.549 +			}
   1.550 +		default:
   1.551 +			ASSERT(0);
   1.552 +			break;
   1.553 +		}
   1.554 +	}
   1.555 +
   1.556 +//Get the new path of the file, folder or drive name based on the TFsMessage function
   1.557 +void FsNotificationHelper::NewPathName(CFsClientMessageRequest& aRequest, TPtrC& aNewPath)
   1.558 +	{
   1.559 +	__PRINT(_L("FsNotificationHelper::NewPathName"));
   1.560 +	//Get the notification type
   1.561 +	TInt function = aRequest.Operation()->Function();
   1.562 +
   1.563 +	//Get the filename(s)
   1.564 +	switch(function)
   1.565 +		{
   1.566 +		case EFsFileRename:			//EParseDst | EParseSrc,
   1.567 +		case EFsRename:				//EParseDst | EParseSrc,
   1.568 +		case EFsReplace:			//EParseDst | EParseSrc,
   1.569 +			{
   1.570 +			aNewPath.Set(aRequest.Dest().FullName());
   1.571 +			break;
   1.572 +			}
   1.573 +		case EFsSetDriveName:		//ESync
   1.574 +			{
   1.575 +			TFileName name;
   1.576 +			aRequest.ReadL(KMsgPtr1, name);
   1.577 +			aNewPath.Set(name);
   1.578 +			break;
   1.579 +			}
   1.580 +		case EFsSetVolume:			//0
   1.581 +			{
   1.582 +			TFileName name;
   1.583 +			aRequest.ReadL(KMsgPtr0, name);
   1.584 +			aNewPath.Set(name);
   1.585 +			break;
   1.586 +			}
   1.587 +		default:
   1.588 +			{
   1.589 +			ASSERT(0);
   1.590 +			break;
   1.591 +			}
   1.592 +		}
   1.593 +	}
   1.594 +
   1.595 +//Get the size of the notification based on its type
   1.596 +TInt FsNotificationHelper::NotificationSize(CFsClientMessageRequest& aRequest, TFsNotification::TFsNotificationType aNotificationType, const TDesC& aName)
   1.597 +	{
   1.598 +	__PRINT(_L("FsNotificationHelper::NotificationSize"));
   1.599 +	
   1.600 +	/*
   1.601 +	 * If there are no new names, the order of the data in the buffer is:
   1.602 +	 * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   1.603 +	 * Word2   : NotificationType (Lower 2 bytes)
   1.604 +	 * Word(s) : Path (TText8) , [Any sub-class members]
   1.605 +	 * 
   1.606 +	 * Else for notification types ERename, EVolumeName and EDriveName the order is:
   1.607 +	 * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   1.608 +	 * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   1.609 +	 * Word(s) : Path (TText8) , NewName (TText8)
   1.610 +	 * 
   1.611 +	 * EOverflow size: KNotificationHeaderSize
   1.612 +	 */	
   1.613 +	
   1.614 +	TInt size = KNotificationHeaderSize + Align4(aName.Size());
   1.615 +	
   1.616 +	switch(aNotificationType)
   1.617 +		{
   1.618 +		//NewName
   1.619 + 		case TFsNotification::ERename:
   1.620 +		case TFsNotification::EVolumeName:
   1.621 +		case TFsNotification::EDriveName:
   1.622 +			{
   1.623 +			TPtrC dest;
   1.624 +			NewPathName(aRequest,dest);
   1.625 +			size += Align4(dest.Size()); 
   1.626 +			break;
   1.627 +			}
   1.628 +		case TFsNotification::EFileChange:
   1.629 +			{
   1.630 +			size += sizeof(TInt64);
   1.631 +			break;
   1.632 +			}
   1.633 +		case TFsNotification::EAttribute:
   1.634 +			{
   1.635 +			size += sizeof(TUint64);
   1.636 +			break;
   1.637 +			}
   1.638 +		case TFsNotification::ECreate: 
   1.639 +		case TFsNotification::EDelete:
   1.640 +		case TFsNotification::EMediaChange:
   1.641 +			{
   1.642 +			break;
   1.643 +			}
   1.644 +		default:
   1.645 +			{
   1.646 +			ASSERT(0);
   1.647 +			break;
   1.648 +			}
   1.649 +		}
   1.650 +	return (TUint16) size;
   1.651 +	}
   1.652 +
   1.653 +TFsNotification::TFsNotificationType FsNotificationHelper::NotificationType(TInt& aIndex)
   1.654 +	{
   1.655 +	__PRINT(_L("FsNotificationHelper::NotificationType(TInt)"));
   1.656 +	__ASSERT_DEBUG(aIndex < KNumRegisterableFilters, Fault(ENotificationFault));
   1.657 +	
   1.658 +	switch(aIndex) //No break statements here on purpose
   1.659 +		{
   1.660 +		case 7 : return TFsNotification::EMediaChange;
   1.661 +		case 6 : return TFsNotification::EDriveName;
   1.662 +		case 5 : return TFsNotification::EVolumeName;
   1.663 +		case 4 : return TFsNotification::EDelete;
   1.664 +		case 3 : return TFsNotification::EAttribute;
   1.665 +		case 2 : return TFsNotification::ECreate;
   1.666 +		case 1 : return TFsNotification::ERename;
   1.667 +		case 0 : return TFsNotification::EFileChange;
   1.668 +		default: ASSERT(0); return (TFsNotification::TFsNotificationType) 0;
   1.669 +		}
   1.670 +	}
   1.671 +
   1.672 +//Get the array index of the notification based on its type
   1.673 +TInt FsNotificationHelper::TypeToIndex(TFsNotification::TFsNotificationType aType)
   1.674 +	{
   1.675 +	__PRINT(_L("FsNotificationHelper::ArrayIndex"));
   1.676 +
   1.677 +	TInt index = 0; 
   1.678 +	switch(aType) //No break statements here on purpose
   1.679 +		{
   1.680 +		case TFsNotification::EMediaChange: index++;
   1.681 +		case TFsNotification::EDriveName:	index++;
   1.682 +		case TFsNotification::EVolumeName:	index++;
   1.683 +		case TFsNotification::EDelete:	 	index++;
   1.684 +		case TFsNotification::EAttribute:	index++;
   1.685 +		case TFsNotification::ECreate:	 	index++;
   1.686 +		case TFsNotification::ERename:	 	index++;
   1.687 +		case TFsNotification::EFileChange:	// skip;
   1.688 +		default: break;
   1.689 +		}
   1.690 +	__ASSERT_DEBUG(index < KNumRegisterableFilters, Fault(ENotificationFault));
   1.691 +	return index;
   1.692 +	}
   1.693 +
   1.694 +TInt FsNotificationHelper::DriveNumber(const TPtrC& aPath)
   1.695 +	{
   1.696 +	if(aPath.Length() >= 2 && ((TChar)aPath[1])==(TChar)':')
   1.697 +		{
   1.698 +		TChar driveChar = ((TChar)aPath[0]);
   1.699 +		driveChar.UpperCase();
   1.700 +		TInt driveNum = driveChar-(TChar)'A'; 
   1.701 +		return driveNum;
   1.702 +		}
   1.703 +	else
   1.704 +		{
   1.705 +		return KErrNotFound;
   1.706 +		}
   1.707 +	}
   1.708 +
   1.709 +//Get the attributes set and cleared
   1.710 +void FsNotificationHelper::Attributes(CFsClientMessageRequest& aRequest, TUint& aSet, TUint& aClear)
   1.711 +	{
   1.712 +	__PRINT(_L("FsNotificationHelper::Attributes"));
   1.713 +
   1.714 +	TInt function = aRequest.Operation()->Function();
   1.715 +	const RMessage2& msg = aRequest.Message();
   1.716 +
   1.717 +	switch(function)
   1.718 +		{
   1.719 +		case EFsFileSet:
   1.720 +			{
   1.721 +			aSet = msg.Int1();
   1.722 +			aClear = msg.Int2();
   1.723 +			break;
   1.724 +			}
   1.725 +		case EFsFileSetAtt:
   1.726 +			{
   1.727 +			aSet = msg.Int0();
   1.728 +			aClear = msg.Int1();
   1.729 +			break;
   1.730 +			}
   1.731 +		case EFsSetEntry:
   1.732 +			{
   1.733 +			aSet = msg.Int2();
   1.734 +			aClear = msg.Int3();
   1.735 +			break;
   1.736 +			}
   1.737 +		default:
   1.738 +			{
   1.739 +			ASSERT(0);
   1.740 +			break;
   1.741 +			}
   1.742 +		}
   1.743 +	}
   1.744 +
   1.745 +
   1.746 +TBool CFsNotifyRequest::ValidateNotification(TInt aNotificationSize, TInt& aServerTail)
   1.747 +	{
   1.748 +	__PRINT(_L("CFsNotifyRequest::ValidateNotification"));
   1.749 +	//RDebug::Print(_L("CFsNotifyRequest::ValidateNotification - iServerTail=%d, aServerTail=%d, iClientTail=%d,iClientHead=%d, aNotificationSize=%d"),iServerTail,aServerTail,iClientTail,iClientHead,aNotificationSize);
   1.750 +	//
   1.751 +	//Start Validation
   1.752 +	//
   1.753 +	TBool overflow = EFalse;
   1.754 +	
   1.755 +	//Check that we have not filled the buffer
   1.756 +    if (aServerTail == iClientHead)
   1.757 +        {
   1.758 +        // Buffer is empty when Client Tail = Client Head
   1.759 +        if (iClientHead != iClientTail)
   1.760 +        	{
   1.761 +			overflow = ETrue;
   1.762 +            return overflow;            
   1.763 +			}
   1.764 +        }
   1.765 +
   1.766 +	//Work out remaining size taking account of whether the end position is
   1.767 +	//before or after the overflow position.
   1.768 +	TInt remainingSize = (iClientHead > aServerTail)
   1.769 +			? iClientHead - aServerTail 
   1.770 +			: iClientBufferSize - (aServerTail - iClientHead);
   1.771 +
   1.772 +    TInt reservedSize = aNotificationSize;
   1.773 +    // + Save additional space for OVERFLOW
   1.774 +    reservedSize += KNotificationHeaderSize;
   1.775 +
   1.776 +	//
   1.777 +    // Have we wrapped around already?
   1.778 +    //
   1.779 +    if (iClientHead > aServerTail)
   1.780 +        {
   1.781 +		// Yes,
   1.782 +		// Buffer looks something like this:
   1.783 +		//
   1.784 +        //            |CH             
   1.785 +        // [5678------1234]
   1.786 +        //     |ST		
   1.787 +
   1.788 +		//
   1.789 +		//  Check if we can insert in the middle section:
   1.790 +		//
   1.791 +		if (remainingSize < reservedSize)
   1.792 +			{
   1.793 +			overflow = ETrue;
   1.794 +			}	
   1.795 +		//else:
   1.796 +		// 	{
   1.797 +		// 	We add new notification to middle 
   1.798 +        //	[5678***---1234]
   1.799 +        // 	}
   1.800 +		//
   1.801 +		return overflow;
   1.802 +        }
   1.803 +
   1.804 +
   1.805 +	//
   1.806 +    // We have not wrapped around yet..
   1.807 +    //
   1.808 +    // Buffer looks something like this:
   1.809 +    //
   1.810 +    //    |CH      
   1.811 +    // [--123456789--]
   1.812 +    //            |ST
   1.813 +    //
   1.814 +
   1.815 +
   1.816 +	//
   1.817 +    // Check up-front whether its possible for overflow to go at the beginning.
   1.818 +    // If there is not enough space at the start for overflow then we need to
   1.819 +    // check that's there's space for overflow at the end and must not rollover.
   1.820 +    //
   1.821 +    TBool canRollOver = ETrue;
   1.822 +    
   1.823 +    if (iClientHead < KNotificationHeaderSize)
   1.824 +        {
   1.825 +		//
   1.826 +        //  |CH      
   1.827 +        // [123456789----]
   1.828 +        //          |ST
   1.829 +        //
   1.830 +        // No space for overflow at the beginning of buffer.
   1.831 +        //
   1.832 +        canRollOver = EFalse; 
   1.833 +        }
   1.834 +
   1.835 +	//
   1.836 +    // IF: Cannot rollover
   1.837 +    //
   1.838 +    if (!canRollOver)
   1.839 +        {
   1.840 +        //IF (notification + overflow) does not fit at the end overflow now.
   1.841 +        if ((iClientBufferSize - aServerTail) < reservedSize)
   1.842 +            {
   1.843 +            overflow = ETrue;
   1.844 +            }        
   1.845 +        //Else
   1.846 +        //	{
   1.847 +		//	Add notification (**) to end [---12345678**---]
   1.848 +		//	}
   1.849 +
   1.850 +        }
   1.851 +    else 
   1.852 +	// Can rollover  
   1.853 +	// - need to check that notification fits at the end
   1.854 +	//   or that notification+overflow fits at the beginning.
   1.855 +        {
   1.856 +        // If not enough space at end, rollover
   1.857 +        if ((iClientBufferSize - aServerTail) < aNotificationSize)
   1.858 +            {
   1.859 +			//
   1.860 +			// Add notification to start and fill end with Filler char 
   1.861 +            // [----0123456789#]
   1.862 +            //
   1.863 +            
   1.864 +            // IF we are not at the very end of the buffer,
   1.865 +			// insert a KNotificationBufferFiller at iServerTail.
   1.866 +			// When the client reads this, it sets iHead to 0 and reads from there.
   1.867 +			if(iServerTail != iClientBufferSize)
   1.868 +				{
   1.869 +				//If there is space it will always be at least 1 word big
   1.870 +				TPtrC8 fillerDes((TText8*) &KNotificationBufferFiller, sizeof(TUint));
   1.871 +				iBufferMsg.Write(KMsgPtr0, fillerDes, aServerTail);
   1.872 +				}
   1.873 +
   1.874 +            // Now that we have rolled over we need to check whether there is
   1.875 +            // space at the beginning for notification + overflow
   1.876 +			// We already know that overflow fits.
   1.877 +            if (reservedSize > iClientHead)
   1.878 +                {
   1.879 +                //  [ov--0123456789-]
   1.880 +                overflow = ETrue;
   1.881 +                }
   1.882 +			//
   1.883 +			// Add notification/overflow to the beginning
   1.884 +			//  	[**--0123456789(#)]
   1.885 +			//
   1.886 +			aServerTail = 0;
   1.887 +			}
   1.888 +		//
   1.889 +		// else - notification fits at the end so there is nothing to do here.
   1.890 +		//
   1.891 +		//
   1.892 +        }
   1.893 +    //
   1.894 +    //End Validation
   1.895 +    //
   1.896 +    return overflow;
   1.897 +    }
   1.898 +
   1.899 +// Called from FsNotificationManager::HandleChange().
   1.900 +// Sends notifications into the client's buffer.
   1.901 +// If there is a iClientMsg then this is the first time this
   1.902 +// has been called since the client called RequestNotifications.
   1.903 +// In this situation we complete the client request.
   1.904 +TInt CFsNotifyRequest::NotifyChange(CFsClientMessageRequest* aRequest,const TDesC& aName, TFsNotification::TFsNotificationType aNotificationType, CFsNotificationBlock& aBlock)
   1.905 +	{
   1.906 +	/*
   1.907 +	 * Different notification types have different data associated with them.
   1.908 +	 * 
   1.909 +	 * All types EXCEPT for ERename, EVolumeName and EDriveName have the following data 
   1.910 +	 * and are aligned in the buffer like so:
   1.911 +	 * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   1.912 +	 * Word2   : NotificationType (Lower 2 bytes)
   1.913 +	 * Word(s) : Path (TText8) , [Any sub-class members]
   1.914 +	 * 
   1.915 +	 * Else for notification types ERename, EVolumeName and EDriveName the order is:
   1.916 +	 * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   1.917 +	 * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   1.918 +	 * Word(s) : Path (TText8) , NewName (TText8)
   1.919 +	 * 
   1.920 +	 * Overflow notification type doesn't have a name, so its namesize is 0
   1.921 +	 * and there will be no Word3.
   1.922 +	 */	
   1.923 +	
   1.924 +	__PRINT(_L("CFsNotifyRequest::NotifyChange()"));
   1.925 +
   1.926 +	TInt notificationSize = FsNotificationHelper::NotificationSize(*aRequest,aNotificationType,aName);
   1.927 +	
   1.928 +	iClientSyncLock.Wait();
   1.929 +	iTailSemaphore.Wait();
   1.930 +	
   1.931 +	TInt tail = iServerTail;
   1.932 +	
   1.933 +	//Validation
   1.934 +	TBool overflow = ValidateNotification(notificationSize, tail);
   1.935 +		
   1.936 +	//Now that we know there is enough space in the buffer we can write 
   1.937 +	//the standard attributes that all notifications have.
   1.938 +
   1.939 +	//We can store the size of the notification 
   1.940 +	//and the size of the name in the same word.
   1.941 +	
   1.942 +	TUint16 nameLen = 0;	//Overflow has no name
   1.943 +	TInt notifSize = KNotificationHeaderSize;
   1.944 +	if(!overflow)
   1.945 +		{
   1.946 +		nameLen = (TUint16)aName.Size();
   1.947 +		notifSize = notificationSize;
   1.948 +		}
   1.949 +	else 
   1.950 +		{
   1.951 +		aNotificationType = TFsNotification::EOverflow;
   1.952 +		}	
   1.953 +
   1.954 +	iServerTail = tail + notifSize;
   1.955 +	iTailSemaphore.Signal();
   1.956 +	
   1.957 +	TInt writeOffset = 0;	//Where to write in the block
   1.958 +	
   1.959 +	//Store notification Size and NameSize (Word1)
   1.960 +	TUint sizeNameLen = (notifSize << 16) | nameLen;	
   1.961 +	memcpy((TText8*)aBlock.Data()+writeOffset,&sizeNameLen,sizeof(TUint));
   1.962 +	writeOffset+=sizeof(TUint);
   1.963 +
   1.964 +	TPtrC newName;
   1.965 +	
   1.966 +	if (aNotificationType == TFsNotification::ERename ||
   1.967 +		aNotificationType == TFsNotification::EVolumeName ||
   1.968 +		aNotificationType == TFsNotification::EDriveName)
   1.969 +		{
   1.970 +		FsNotificationHelper::NewPathName(*aRequest,newName);
   1.971 +		//Store NewNameSize and notification Type (Word2)
   1.972 +		TUint typeNewNameLen = ((TUint16)newName.Size() << 16) | (TUint16)aNotificationType;
   1.973 +		memcpy((TText8*)aBlock.Data()+writeOffset,&typeNewNameLen,sizeof(TUint));
   1.974 +		}
   1.975 +	else
   1.976 +		{
   1.977 +		//Store notification Type (Word2)
   1.978 +		memcpy((TText8*)aBlock.Data()+writeOffset,&aNotificationType,sizeof(TUint));
   1.979 +		}
   1.980 +	writeOffset+=sizeof(TUint);
   1.981 +	
   1.982 +	CFileShare* share = NULL;
   1.983 +    CFileCB* file = NULL;
   1.984 +    if(aRequest) //Don't always have a request such as when called from localdrives.
   1.985 +        {
   1.986 +        GetFileFromScratch(aRequest, share, file);
   1.987 +        }
   1.988 +    
   1.989 +    //
   1.990 +    //Store UID
   1.991 +    /*
   1.992 +	TUid uid;
   1.993 +	uid.iUid = KErrUnknown;
   1.994 +	if(aRequest && aRequest->Operation()->iFunction == EFsFileWriteDirty)
   1.995 +	    {
   1.996 +	    uid = aRequest->iUID;
   1.997 +	    }
   1.998 +	else if(aRequest)
   1.999 +	    {
  1.1000 +	    uid = aRequest->Message().Identity();
  1.1001 +	    }
  1.1002 +	memcpy((TText8*)aBlock.Data()+writeOffset,&uid.iUid,sizeof(TUint32));
  1.1003 +	writeOffset+=sizeof(TUint32);
  1.1004 +	*/
  1.1005 +	
  1.1006 +	if(!overflow)
  1.1007 +		{
  1.1008 +		//Store Name (Word3)
  1.1009 +		memcpy((TText8*)aBlock.Data()+writeOffset,aName.Ptr(),aName.Size());
  1.1010 +		writeOffset += Align4(aName.Size());
  1.1011 +		
  1.1012 +
  1.1013 +		switch (aNotificationType)
  1.1014 +			{
  1.1015 +			case TFsNotification::EFileChange:
  1.1016 +				{
  1.1017 +				TInt64 size = 0;
  1.1018 +				size = file->CachedSize64();
  1.1019 +				memcpy((TText8*)aBlock.Data()+writeOffset,&size,sizeof(TInt64));
  1.1020 +				writeOffset += sizeof(TInt64);
  1.1021 +				break;
  1.1022 +				}
  1.1023 +			case TFsNotification::ERename:
  1.1024 +			case TFsNotification::EVolumeName:
  1.1025 +			case TFsNotification::EDriveName:
  1.1026 +				{
  1.1027 +				//Store NewName
  1.1028 +				memcpy((TText8*)aBlock.Data()+writeOffset,newName.Ptr(),newName.Size());
  1.1029 +				writeOffset += Align4(newName.Size());
  1.1030 +				break;
  1.1031 +				}
  1.1032 +			case TFsNotification::EAttribute:
  1.1033 +				{
  1.1034 +				TUint set=0;
  1.1035 +				TUint clear=0;
  1.1036 +				FsNotificationHelper::Attributes(*aRequest,set,clear);
  1.1037 +				TUint64 att = MAKE_TUINT64(set,clear);
  1.1038 +				memcpy((TText8*)aBlock.Data()+writeOffset,&att,sizeof(TUint64));
  1.1039 +				writeOffset += sizeof(TUint64);
  1.1040 +				break;
  1.1041 +				}
  1.1042 +			default:
  1.1043 +				{
  1.1044 +				break;
  1.1045 +				}
  1.1046 +			}
  1.1047 +		}
  1.1048 +	
  1.1049 +	//Write to client buffer
  1.1050 +	TInt r = SynchroniseBuffer(aBlock,tail,notifSize);
  1.1051 +	
  1.1052 +	//Signal the iClientSyncLock. 
  1.1053 +	//When all locks on this are signaled then CompleteClientRequest can be called.
  1.1054 +	//This signal moves when we have a cache system
  1.1055 +	iClientSyncLock.Signal();
  1.1056 +	
  1.1057 +	//We need to complete if this was the first 
  1.1058 +	//write to the client's buffer
  1.1059 +    if (r == KErrNone)
  1.1060 +        {
  1.1061 +		//We need to complete if this was the first 
  1.1062 +		//write to the client's buffer
  1.1063 +        if(ClientMsgHandle()!=0)
  1.1064 +            {
  1.1065 +			//RDebug::Print(_L("CFsNotifyRequest::NotifyChange iClientHead(%d) iClientTail(%d) iServerTail(%d) iClientBufferSize(%d)"),iClientHead,iClientTail,iServerTail,iClientBufferSize);
  1.1066 +            __PRINT4(_L("CFsNotifyRequest::NotifyChange iClientHead(%d) iClientTail(%d) iServerTail(%d) iClientBufferSize(%d)"),iClientHead,iClientTail,iServerTail,iClientBufferSize);
  1.1067 +            CompleteClientRequest(KErrNone);
  1.1068 +            }
  1.1069 +        else if(!overflow)
  1.1070 +            {
  1.1071 +		SetActive(CFsNotifyRequest::EOutstanding);
  1.1072 +            }
  1.1073 +        else //Overflow
  1.1074 +            {
  1.1075 +		SetActive(CFsNotifyRequest::EOutstandingOverflow);
  1.1076 +            }
  1.1077 +        }
  1.1078 +	else // r!=KErrNone
  1.1079 +		{
  1.1080 +		//RDebug::Print(_L("sf_notifier.cpp line %d function = %d, r = %d"),__LINE__, aRequest->FsFunction(),r);
  1.1081 +		//RDebug::Print(_L("iServerTail=%d, tail=%d, iClientBufferSize=%d, overflow=%d"),iServerTail,tail,iClientBufferSize,overflow);
  1.1082 +		}
  1.1083 +	return r;
  1.1084 +	}
  1.1085 +
  1.1086 +#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
  1.1087 +
  1.1088 +//A change has occurred in f32 represented by this
  1.1089 +//request object. Work out which CfsNotify’s are interested
  1.1090 +// (if any) and call CfsNotifyRequest::NotifyChange.
  1.1091 +void FsNotificationManager::HandleChange(CFsClientMessageRequest* aRequest,const TDesC& aOperationName, TFsNotification::TFsNotificationType aType)
  1.1092 +	{
  1.1093 +	__PRINT2(_L("FsNotificationManager::HandleChange() aRequest=0x%x, aType=%d"),&aRequest,aType);
  1.1094 +
  1.1095 +	Lock(); //ToDo: Read Lock (Read/Write Lock)	
  1.1096 +	if(Count())
  1.1097 +		{
  1.1098 +		//Only search while there are filters of this type set up.
  1.1099 +		TInt index = FsNotificationHelper::TypeToIndex(aType);
  1.1100 +		TInt& filterCount = FsNotificationManager::FilterRegister(index);
  1.1101 +		TInt seenFilter = filterCount; //Number of requests set up for this type
  1.1102 +		
  1.1103 +		//Iterate CFsNotifyRequests
  1.1104 +		TInt count = iNotifyRequests->Count();
  1.1105 +		
  1.1106 +		if(aType == TFsNotification::EMediaChange)
  1.1107 +			seenFilter = count;
  1.1108 +		
  1.1109 +		//If there aren't any requests then breakout
  1.1110 +		if(count == 0)
  1.1111 +			{
  1.1112 +			Unlock();
  1.1113 +			return;
  1.1114 +			}
  1.1115 +		
  1.1116 +		TInt driveNum = FsNotificationHelper::DriveNumber(aOperationName); 
  1.1117 +
  1.1118 +		//For every notification request.
  1.1119 +		for(TInt i=0; i<count && seenFilter; ++i)
  1.1120 +			{
  1.1121 +			CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*)(*iNotifyRequests)[i];
  1.1122 +			CFsNotifyRequest::TNotifyRequestStatus status = notifyRequest->ActiveStatus();
  1.1123 +			if(! (status==CFsNotifyRequest::EActive || 
  1.1124 +				  status==CFsNotifyRequest::EOutstanding))
  1.1125 +				{
  1.1126 +				//Not active; check next notification request
  1.1127 +				continue;
  1.1128 +				}
  1.1129 +			
  1.1130 +			//Check whether we are interested in this change.
  1.1131 +			//Get the filters associated with this operation on this drive
  1.1132 +			TFsNotificationTypeArray* filterList = notifyRequest->FilterTypeList(driveNum,index);
  1.1133 +			DoHandleChange(filterList,seenFilter,aRequest,notifyRequest,aOperationName,aType);
  1.1134 +
  1.1135 +			if(aType==TFsNotification::EMediaChange)
  1.1136 +				continue; //next request
  1.1137 +			
  1.1138 +			//If there are still filters to check
  1.1139 +			if(seenFilter)
  1.1140 +				{
  1.1141 +				//Check changes that are not tied to a particular drive
  1.1142 +				filterList = notifyRequest->FilterTypeList(KErrNotFound,index);
  1.1143 +				DoHandleChange(filterList,seenFilter,aRequest,notifyRequest,aOperationName,aType);
  1.1144 +				}
  1.1145 +			}
  1.1146 +		}
  1.1147 +	Unlock();
  1.1148 +	}
  1.1149 +
  1.1150 +//A change has occurred in f32 represented by this
  1.1151 +//request object. Work out which CfsNotify’s are interested
  1.1152 +// (if any) and call CfsNotifyRequest::NotifyChange.
  1.1153 +void FsNotificationManager::HandleChange(CFsClientMessageRequest& aRequest, TFsNotification::TFsNotificationType aType)
  1.1154 +	{
  1.1155 +	__PRINT(_L("FsNotificationManager::HandleChange"));
  1.1156 +	TFileName currentOperationsName;
  1.1157 +	FsNotificationHelper::PathName(aRequest, currentOperationsName);
  1.1158 +	if(currentOperationsName.Length())
  1.1159 +		HandleChange(&aRequest,currentOperationsName,aType);
  1.1160 +	}
  1.1161 +
  1.1162 +//A change has occurred in f32 represented by this
  1.1163 +//request object. Work out which CfsNotify’s are interested
  1.1164 +// (if any) and call CfsNotifyRequest::NotifyChange.
  1.1165 +void FsNotificationManager::HandleChange(CFsClientMessageRequest& aRequest)
  1.1166 +	{
  1.1167 +	if(Count() && aRequest.Message().Handle() != KLocalMessageHandle)
  1.1168 +		{
  1.1169 +		__PRINT(_L("FsNotificationManager::HandleChange"));
  1.1170 +		TFsNotification::TFsNotificationType operationNotificationType;
  1.1171 +		FsNotificationHelper::NotificationType(aRequest.FsFunction(), operationNotificationType);
  1.1172 +		HandleChange(aRequest,operationNotificationType);
  1.1173 +		}
  1.1174 +	}
  1.1175 +
  1.1176 +
  1.1177 +////
  1.1178 +#else
  1.1179 +////
  1.1180 +
  1.1181 +void FsNotificationManager::HandleChange(CFsClientMessageRequest* ,const TDesC&, TFsNotification::TFsNotificationType)
  1.1182 +	{
  1.1183 +	return;
  1.1184 +	}
  1.1185 +
  1.1186 +void FsNotificationManager::HandleChange(CFsClientMessageRequest& , TFsNotification::TFsNotificationType)
  1.1187 +	{
  1.1188 +	return;
  1.1189 +	}
  1.1190 +
  1.1191 +void FsNotificationManager::HandleChange(CFsClientMessageRequest&)
  1.1192 +	{
  1.1193 +	return;
  1.1194 +	}
  1.1195 +
  1.1196 +#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
  1.1197 +
  1.1198 +//Called from FsNotificationManager::DoHandleChange
  1.1199 +FsNotificationManager::TFsNotificationFilterMatch FsNotificationManager::DoMatchFilter(CFsClientMessageRequest* aRequest, const TDesC& aOperationName,CFsNotificationPathFilter& aFilter)
  1.1200 +    {
  1.1201 +    TFsNotificationFilterMatch filterMatch = EDifferent;
  1.1202 +    TParsePtrC parseOp(aOperationName);
  1.1203 +    TPtrC pathOpDes = parseOp.DriveAndPath();
  1.1204 +    TPtrC nameOpDes = parseOp.NameAndExt();
  1.1205 +    TInt pathLength = aFilter.iPath->Des().Length();
  1.1206 +    TInt nameLength = aFilter.iFilename->Des().Length();
  1.1207 +    TInt paths = -1;
  1.1208 +    TInt names = -1;
  1.1209 +    if(pathLength != 0)
  1.1210 +        {
  1.1211 +        paths = pathOpDes.MatchF(aFilter.iPath->Des());
  1.1212 +        }
  1.1213 +    else //if no path filter was set up
  1.1214 +        // then we need to ensure we don't notify on data-caged areas which we shouldn't
  1.1215 +        {
  1.1216 +        TInt r = PathCheck(aRequest,aOperationName.Mid(2),&KCapFsSysFileTemp,&KCapFsPriFileTemp,&KCapFsROFileTemp, __PLATSEC_DIAGNOSTIC_STRING("FsNotificationManager::DoHandleChange"));
  1.1217 +        if(r != KErrNone)
  1.1218 +            return EContinue; //next filter
  1.1219 +        }
  1.1220 +    
  1.1221 +    if(nameLength != 0)
  1.1222 +        {
  1.1223 +        names = nameOpDes.MatchF(aFilter.iFilename->Des());  
  1.1224 +        }
  1.1225 +    //Check: Path & Names Match
  1.1226 +    if((paths == 0 || pathLength==0) &&                             //  paths match && 
  1.1227 +        (names >= 0 || (nameLength==0 && nameOpDes.Length()==0))) // names match OR there are no names (i.e. operation is a dir and no filename filter)
  1.1228 +        {
  1.1229 +         filterMatch = EMatch;
  1.1230 +        }
  1.1231 +    return filterMatch;
  1.1232 +    }
  1.1233 +
  1.1234 +// This is called on a per drive basis.
  1.1235 +void FsNotificationManager::DoHandleChange(TFsNotificationTypeArray* aFilterTypeArray,TInt& aSeenFilter, CFsClientMessageRequest* aRequest, CFsNotifyRequest* aNotifyRequest, const TDesC& aOperationName, TFsNotification::TFsNotificationType& aType)
  1.1236 +	{		
  1.1237 +	__PRINT(_L("FsNotificationManager::DoHandleChange()"));
  1.1238 +	
  1.1239 +	if(!aFilterTypeArray)
  1.1240 +		return;
  1.1241 +	
  1.1242 +	TInt numFilters = aFilterTypeArray->Count();
  1.1243 +	
  1.1244 +	if(aType == TFsNotification::EMediaChange)
  1.1245 +		numFilters = 1; //Only need to notify once per drive.
  1.1246 +		
  1.1247 +	//For every filter in this request
  1.1248 +	for(TInt j = 0; j < numFilters;++j)
  1.1249 +		{
  1.1250 +		//Is the correct notification type
  1.1251 +		aSeenFilter--;
  1.1252 +		
  1.1253 +		TBool filterMatch = EDifferent;
  1.1254 +		if(aType != TFsNotification::EMediaChange)
  1.1255 +			{
  1.1256 +			CFsNotificationPathFilter& filter = *(((*aFilterTypeArray)[j]).iPathFilter);
  1.1257 +			__PRINT2(_L("FsNotificationManager::DoHandleChange() operationName=%S, filterName=%S"),&aOperationName,filter.iPath);
  1.1258 +			
  1.1259 +			filterMatch = DoMatchFilter(aRequest,aOperationName,filter);
  1.1260 +			if(filterMatch == FsNotificationManager::EContinue)
  1.1261 +			    continue; //triggers for data cages
  1.1262 +			
  1.1263 +			//We need to check for changes coming in to a directory when its rename
  1.1264 +			if(aType == TFsNotification::ERename && filterMatch==FsNotificationManager::EDifferent)  
  1.1265 +                {
  1.1266 +                TPtrC aDestinationNamePtrC;
  1.1267 +                FsNotificationHelper::NewPathName(*aRequest,aDestinationNamePtrC);
  1.1268 +                __PRINT2(_L("FsNotificationManager::DoHandleChange() destinationName=%S, filterName=%S"),&aDestinationNamePtrC,filter.iPath);
  1.1269 +                filterMatch = DoMatchFilter(aRequest,aDestinationNamePtrC,filter);
  1.1270 +                }
  1.1271 +			}
  1.1272 +
  1.1273 +		if(filterMatch || (aType == TFsNotification::EMediaChange))//Match or MediaChange (report regardless of filters)
  1.1274 +			{
  1.1275 +			//Matching - Handle change
  1.1276 +			
  1.1277 +			//Get a CFsNotificationBlock to use 
  1.1278 +			//So that we can do IPC from a single place.
  1.1279 +			CFsNotificationBlock* block = iPool->Allocate();
  1.1280 +				
  1.1281 +			TInt r = aNotifyRequest->NotifyChange(aRequest,aOperationName,aType,*block);
  1.1282 +				
  1.1283 +			//Free block
  1.1284 +			iPool->Free(block);
  1.1285 +				
  1.1286 +			if(r != KErrNone)
  1.1287 +				{
  1.1288 +				//Something went wrong writing to the client's buffer
  1.1289 +				aNotifyRequest->SetActive(CFsNotifyRequest::EInactive);
  1.1290 +				if(aNotifyRequest->ClientMsgHandle()!=0)
  1.1291 +					aNotifyRequest->CompleteClientRequest(r,EFalse);
  1.1292 +				break; //Go to outer for (i.e. next request in HandleChange)
  1.1293 +				}
  1.1294 +			}	
  1.1295 +		continue; //next filter
  1.1296 +		}
  1.1297 +	}