os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_notification.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\sfsrv\cl_notification.cpp
    15 // 
    16 //
    17 #include "cl_std.h"
    18 #include "cl_notification.h"
    19 
    20 #ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
    21 /*
    22  * The order of the data in the buffer is:
    23  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
    24  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
    25  * Word3   : UID - NOT YET SUPPORTED
    26  * Word(s) : Path (TText8) , [Any sub-class members]
    27  * 
    28  * The notification size should be located at *this
    29  */ 
    30 TInt TFsNotification::NotificationSize() const
    31 	{
    32 	TInt word1 = *(TInt*)this;
    33 	return (word1 >> 16);
    34 	}
    35  
    36 /*
    37  * The order of the data in the buffer is:
    38  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
    39  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
    40  * Word3   : UID - NOT YET SUPPORTED
    41  * Word(s) : Path (TText8) , [Any sub-class members]
    42  * 
    43  * The notification type should be located at:
    44  * 	*this + sizeof(NotificationSize) + sizeof(PathSize) + sizeof(NewNameSize)
    45  */ 
    46 EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const
    47 	{
    48 	TUint* word2 = PtrAdd((TUint*)this, sizeof(TUint));
    49 	TFsNotificationType ret = (TFsNotificationType)(*word2 & 0x0000FFFF);
    50 	//Check it is a valid type
    51 	__ASSERT_DEBUG(!((TInt)ret & ~KNotificationValidFiltersMask) || (ret == EOverflow), Panic(ENotificationPanic));
    52 	return ret; //Returns the lower 2 bytes of Word2
    53 	}
    54 
    55 /*
    56  * The order of the data in the buffer is:
    57  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
    58  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
    59  * Word3   : UID - NOT YET SUPPORTED
    60  * Word(s) : Path (TText8) , [Any sub-class members]
    61  * 
    62  * The path size should be located at *this + sizeof(NotificationSize)
    63  */ 
    64 TInt TFsNotification::PathSize() const
    65 	{
    66 	//Notification of type EOverflow does not have a path associated with it
    67 	__ASSERT_DEBUG(NotificationType() != EOverflow,Panic(ENotificationPanic));
    68 	TUint ret = (*(TUint*)this & 0x0000FFFF); //Returns the lower 2 bytes of Word1
    69 	return (TInt)ret;
    70 	}
    71 
    72 /*
    73  * The order of the data in the buffer is:
    74  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
    75  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
    76  * Word3   : UID - NOT YET SUPPORTED
    77  * Word(s) : Path (TText8) , [Any sub-class members]
    78  * 
    79  * The path should be located at: *this + KNotificationHeaderSize
    80  */
    81 EXPORT_C TInt TFsNotification::Path(TPtrC& aPath) const
    82 	{
    83 	//Notification of type EOverflow does not have a path associated with it
    84 	if(NotificationType() == EOverflow)
    85 		return KErrNotSupported;
    86 
    87 	TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize);
    88 	aPath.Set(pathPtr,PathSize()/2);
    89 	return KErrNone;
    90 	}
    91 
    92 /*
    93  * The order of the data in the buffer is:
    94  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
    95  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
    96  * Word3   : UID - NOT YET SUPPORTED
    97  * Word(s) : Path (TText8) , [Any sub-class members]
    98  * 
    99  * The new name size should be located at: *this + sizeof(NotificationSize) + sizeof(PathSize)
   100  */ 
   101 TInt TFsNotification::NewNameSize() const
   102 	{
   103 	//The only notifications containing a new name are ERename, EVolumeName and EDriveName
   104 	__ASSERT_DEBUG((NotificationType() == ERename ||
   105 					NotificationType() == EVolumeName ||
   106 					NotificationType() == EDriveName),Panic(ENotificationPanic));
   107 	TInt* word2 = PtrAdd((TInt*)this, sizeof(TInt));
   108 	return ((*word2) >> 16);
   109 	}
   110 
   111 /*
   112  * The order of the data in the buffer is:
   113  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   114  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   115  * Word3   : UID - NOT YET SUPPORTED
   116  * Word(s) : Path (TText8) , [Any sub-class members]
   117  * 
   118  * The new name should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
   119  */
   120 EXPORT_C TInt TFsNotification::NewName(TPtrC& aNewName) const
   121 	{
   122 	//Only ERename, EVolumeName and EDriveName have second paths
   123 	//Notification of type EOverflow does not have a path associated with it
   124 	TFsNotificationType notificationType = NotificationType();
   125 	if((notificationType != ERename &&
   126 		notificationType != EVolumeName &&
   127 		notificationType != EDriveName) ||
   128 		notificationType == EOverflow)
   129 		{
   130 		return KErrNotSupported;
   131 		}
   132 
   133 	TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize + Align4(PathSize()));
   134 	aNewName.Set(pathPtr,NewNameSize()/2);
   135 	return KErrNone;
   136 	}
   137 
   138 /*
   139  * The order of the data in the buffer is:
   140  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   141  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   142  * Word3   : UID - NOT YET SUPPORTED
   143  * Word(s) : Path (TText8) , [Any sub-class members]
   144  * 
   145  * The attribute should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
   146  */
   147 EXPORT_C TInt TFsNotification::Attributes(TUint& aSetAtt, TUint& aClearAtt) const
   148 	{
   149 	if(NotificationType() != EAttribute)
   150 		return KErrNotSupported;
   151 
   152 	TUint* clearAttptr = PtrAdd((TUint*)this, KNotificationHeaderSize + Align4(PathSize()));
   153 	aClearAtt = *clearAttptr;
   154 	aSetAtt = *PtrAdd((TUint*)clearAttptr, sizeof(TUint));
   155 	return KErrNone;
   156 	}
   157 
   158 /*
   159  * The order of the data in the buffer is:
   160  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   161  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   162  * Word3   : UID - NOT YET SUPPORTED
   163  * Word(s) : Path (TText8) , [Any sub-class members]
   164  * 
   165  * The size should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
   166  */
   167 EXPORT_C TInt TFsNotification::FileSize(TInt64& aSize) const
   168 	{
   169 	if(NotificationType() != EFileChange)
   170 		return KErrNotSupported;
   171 
   172 	aSize = *PtrAdd((TInt64*)this, KNotificationHeaderSize + Align4(PathSize()));
   173 	return KErrNone;
   174 	}
   175 
   176 /*
   177  * The order of the data in the buffer is:
   178  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   179  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   180  * Word3   : UID
   181  * Word(s) : Path (TText8) , [Any sub-class members]
   182 
   183 EXPORT_C TInt TFsNotification::DriveNumber(TInt& aDriveNumber) const
   184 	{
   185 	TPtrC path(NULL,0);
   186 	TInt r = Path(path);
   187 	if(r == KErrNone)
   188 		{
   189 		if(path.Length() >= 2 && ((TChar)path[1]==(TChar)':'))
   190 			{
   191 			r = RFs::CharToDrive(path[0],aDriveNumber);
   192 			}
   193 		}
   194 	return r;
   195 	}
   196 	*/
   197 
   198 /*
   199  * The order of the data in the buffer is:
   200  * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
   201  * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
   202  * Word3   : UID
   203  * Word(s) : Path (TText8) , [Any sub-class members]
   204 
   205 EXPORT_C TInt TFsNotification::UID(TUid& aUID) const
   206     {
   207     TUint* word3 = PtrAdd((TUint*)this, sizeof(TUint)*2);
   208     aUID.iUid = *word3;
   209     return KErrNone; 
   210     }
   211 	*/
   212 
   213 
   214 CFsNotificationList* CFsNotificationList::NewL(TInt aBufferSize)
   215 	{
   216 	CFsNotificationList* self = new(ELeave) CFsNotificationList;
   217 	CleanupStack::PushL(self);
   218 	self->iBuf = HBufC8::NewL(aBufferSize);
   219 	self->iBufferPtr.Set((TUint8*)self->iBuf->Ptr(),0,self->iBuf->Des().MaxSize());
   220 	CleanupStack::Pop(self);
   221 	return self;
   222 	}
   223 
   224 CFsNotificationList::CFsNotificationList()
   225 : iTailPckg(iTail), iBufferPtr(NULL,0)
   226 	{
   227 	}
   228 
   229 CFsNotificationList::~CFsNotificationList()
   230 	{
   231 	delete iBuf;
   232 	}
   233 
   234 TInt CFsNotificationList::BufferSize() const 
   235 	{
   236 	return iBuf->Size();
   237 	}
   238 
   239 const TFsNotification * CFsNotificationList::NextNotification()
   240 	{
   241 	TFsNotification* notification;
   242 
   243 	if(iHead == iTail)
   244 		{
   245 		return NULL;
   246 		}
   247 	TUint* startptr = (TUint*)iBuf->Ptr();
   248 	TUint* nptr = PtrAdd(startptr, iHead);
   249 	TInt bufferSize = iBuf->Des().MaxSize();
   250 	TUint* endOfBuffer = PtrAdd(startptr, bufferSize);
   251 
   252 	if(*nptr == KNotificationBufferFiller || nptr == endOfBuffer)
   253 		{
   254 		iHead = 0;
   255 		notification = (TFsNotification*)startptr;
   256 		}
   257 	else
   258 		{
   259 		notification = (TFsNotification*)nptr;
   260 		}
   261 	iHead += notification->NotificationSize();
   262 	if(iHead  == bufferSize)
   263 		iHead = 0;
   264 	
   265 	return notification;
   266 	}
   267 
   268 
   269 EXPORT_C CFsNotify* CFsNotify::NewL(RFs& aFs, TInt aBufferSize)
   270 	{
   271 	CFsNotify* self=new(ELeave) CFsNotify;
   272 	CleanupStack::PushL(self);
   273 
   274 	//Making sure buffer size is at least minimally large and not too big
   275 	if(aBufferSize > (KMaxTInt/2))
   276 		{
   277 		User::Leave(KErrArgument);
   278 		}
   279 	else if(aBufferSize < KMinNotificationBufferSize)
   280 		{
   281 		aBufferSize = KMinNotificationBufferSize;
   282 		}
   283 	
   284 	self->ConstructL(aFs, Align4(aBufferSize));
   285 	CleanupStack::Pop(self);
   286 	return self;
   287 	}
   288 
   289 void CFsNotify::ConstructL(RFs& aFs,TInt aBufferSize)
   290 	{
   291 	iBody = new(ELeave) CFsNotifyBody();
   292 	iBody->iBuffer = CFsNotificationList::NewL(aBufferSize);
   293 	User::LeaveIfError(iBody->iFsNotify.Open(aFs,iBody->iBuffer,iBody->iBufferStatus));
   294 	}
   295 
   296 CFsNotify::CFsNotify()
   297 	{
   298 	}
   299 
   300 EXPORT_C CFsNotify::~CFsNotify()
   301 	{
   302 	if(iBody)
   303 		{
   304 		if(iBody->iBuffer)
   305 			{
   306 			iBody->iBuffer->iTail = 0;
   307 			iBody->iBuffer->iHead = 0;
   308 			iBody->iFsNotify.Close();
   309 			delete iBody->iBuffer;
   310 			}
   311 		}
   312 	delete iBody;
   313 	}
   314 
   315 CFsNotifyBody::CFsNotifyBody()
   316 	{
   317 	}
   318 
   319 CFsNotifyBody::~CFsNotifyBody()
   320 	{
   321 	}
   322 
   323 EXPORT_C TInt CFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename)
   324 	{
   325 	if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0))
   326 		return KErrArgument;
   327 
   328 	return iBody->iFsNotify.AddNotification(aNotificationType, aPath, aFilename);
   329 	}
   330 
   331 //Removes notification request, does not close session
   332 EXPORT_C TInt CFsNotify::RemoveNotifications()
   333 	{
   334 	return iBody->iFsNotify.RemoveNotifications();
   335 	}
   336 
   337 EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus& aStatus)
   338 	{
   339 	if(aStatus == KRequestPending || ((iBody->iClientStatus != NULL) && (*iBody->iClientStatus == KRequestPending)))
   340 		return KErrInUse;
   341 	
   342 	iBody->iClientStatus = &aStatus;
   343 	//Read the new notifications which will start at tail.
   344 	//(Also this forbids user access outside permitted range)
   345 	iBody->iBuffer->iHead = iBody->iBuffer->iTail; 
   346 	iBody->iFsNotify.RequestNotifications(aStatus, iBody->iBuffer->iTailPckg);
   347 	return KErrNone;
   348 	}
   349 
   350 //Cancels notification request, does not close session
   351 EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus& aStatus)
   352 	{
   353 	if(aStatus != KRequestPending || &aStatus != iBody->iClientStatus)
   354 		return KErrInUse;
   355 	
   356 	TInt r = iBody->iFsNotify.CancelNotifications();
   357 	aStatus = !KRequestPending;
   358 	iBody->iBuffer->iHead = 0;
   359 	iBody->iBuffer->iTail = 0;
   360 	return r;
   361 	}
   362 
   363 EXPORT_C const TFsNotification *  CFsNotify::NextNotification()
   364 	{
   365 	return iBody->iBuffer->NextNotification();
   366 	}
   367 
   368 
   369 TInt RFsNotify::Open(RFs& aFs, CFsNotificationList* aBuffer, TRequestStatus& aBufferStatus)
   370 	{
   371 	if(aBuffer == NULL || aBuffer->iBuf == NULL || &aFs == NULL || &aBufferStatus==NULL)
   372 		return KErrArgument;
   373 	
   374 	TInt err = CreateSubSession(aFs,EFsNotificationOpen);
   375 	if (err == KErrNone)
   376 		{
   377 		aBufferStatus = KRequestPending;
   378 		//memclr((TUint8*)aBuffer->iBuf->Ptr(),aBuffer->iBuf->Des().MaxSize());
   379 		SendReceive(EFsNotificationBuffer, TIpcArgs(&aBuffer->iBufferPtr,aBuffer->iBuf->Des().MaxSize()), aBufferStatus);
   380 		}
   381 	return err;
   382 	}
   383 
   384 void RFsNotify::Close()
   385 	{
   386 	CloseSubSession(EFsNotificationSubClose);
   387 	}
   388 
   389 /*
   390 [Re]Issues notification request
   391 Updates buffer, if supplied.
   392 
   393 @return - last readable index of buffer.
   394 */
   395 void RFsNotify::RequestNotifications(TRequestStatus& aStatus, TPckg<TInt>& aTailPckg)
   396 	{
   397 	aStatus = KRequestPending;
   398 	SendReceive(EFsNotificationRequest,TIpcArgs(&aTailPckg),aStatus);
   399 	}
   400 
   401 TInt RFsNotify::CancelNotifications()
   402 	{
   403 	//there can only be one outstanding notification request at a time
   404 	return (SendReceive(EFsNotificationCancel));
   405 	}
   406 
   407 //Adds notification filter
   408 TInt RFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename)
   409 	{
   410 	if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0))
   411 		return KErrArgument;
   412 	
   413 	return (SendReceive(EFsNotificationAdd,TIpcArgs(aNotificationType,&aPath,&aFilename)));
   414 	}
   415 
   416 //Removes request, does not close session
   417 TInt RFsNotify::RemoveNotifications()
   418 	{
   419 	return(SendReceive(EFsNotificationRemove));
   420 	}
   421 #else //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
   422 
   423 EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const
   424 	{
   425 	Panic(ENotificationPanic);
   426 	return (TFsNotification::TFsNotificationType)0;
   427 	}
   428 
   429 EXPORT_C TInt TFsNotification::Path(TPtrC&) const
   430 	{
   431 	Panic(ENotificationPanic);
   432 	return KErrNotSupported;
   433 	}
   434 
   435 EXPORT_C TInt TFsNotification::NewName(TPtrC&) const
   436 	{
   437 	Panic(ENotificationPanic);
   438 	return KErrNotSupported;
   439 	}
   440 
   441 EXPORT_C TInt TFsNotification::Attributes(TUint&,TUint&) const
   442 	{
   443 	Panic(ENotificationPanic);
   444 	return KErrNotSupported;
   445 	}
   446 
   447 EXPORT_C TInt TFsNotification::FileSize(TInt64&) const
   448 	{
   449 	Panic(ENotificationPanic);
   450 	return KErrNotSupported;
   451 	}
   452 
   453 /*
   454 EXPORT_C TInt TFsNotification::DriveNumber(TInt&) const
   455 	{
   456 	Panic(ENotificationPanic);
   457 	return KErrNotSupported;
   458 	}
   459 	
   460 EXPORT_C TInt TFsNotification::UID(TUid& aUID) const
   461     {
   462  	Panic(ENotificationPanic);
   463 	return KErrNotSupported;
   464     }
   465 */
   466 
   467 EXPORT_C CFsNotify* CFsNotify::NewL(RFs& , TInt)
   468 	{
   469 	Panic(ENotificationPanic);
   470 	User::Leave(KErrNotSupported);
   471 	return NULL;
   472 	}
   473 
   474 EXPORT_C CFsNotify::~CFsNotify()
   475 	{
   476 	Panic(ENotificationPanic);
   477 	}
   478 
   479 EXPORT_C TInt CFsNotify::AddNotification(TUint, const TDesC&, const TDesC&)
   480 	{
   481 	Panic(ENotificationPanic);
   482 	return KErrNotSupported;
   483 	}
   484 
   485 EXPORT_C TInt CFsNotify::RemoveNotifications()
   486 	{
   487 	Panic(ENotificationPanic);
   488 	return KErrNotSupported;
   489 	}
   490 
   491 EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus&)
   492 	{
   493 	Panic(ENotificationPanic);
   494 	return KErrNotSupported;
   495 	}
   496 
   497 EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus&)
   498 	{
   499 	Panic(ENotificationPanic);
   500 	return KErrNotSupported;
   501 	}
   502 
   503 EXPORT_C const TFsNotification *  CFsNotify::NextNotification()
   504 	{
   505 	Panic(ENotificationPanic);
   506 	return NULL;
   507 	}
   508 
   509 CFsNotificationList::~CFsNotificationList()
   510 	{
   511 	Panic(ENotificationPanic);
   512 	}
   513 
   514 CFsNotifyBody::CFsNotifyBody()
   515 	{
   516 	Panic(ENotificationPanic);
   517 	}
   518 
   519 CFsNotifyBody::~CFsNotifyBody()
   520 	{
   521 	Panic(ENotificationPanic);
   522 	}
   523 
   524 #endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
   525