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 + }