--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfsrv/cl_notification.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,525 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32\sfsrv\cl_notification.cpp
+//
+//
+#include "cl_std.h"
+#include "cl_notification.h"
+
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The notification size should be located at *this
+ */
+TInt TFsNotification::NotificationSize() const
+ {
+ TInt word1 = *(TInt*)this;
+ return (word1 >> 16);
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The notification type should be located at:
+ * *this + sizeof(NotificationSize) + sizeof(PathSize) + sizeof(NewNameSize)
+ */
+EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const
+ {
+ TUint* word2 = PtrAdd((TUint*)this, sizeof(TUint));
+ TFsNotificationType ret = (TFsNotificationType)(*word2 & 0x0000FFFF);
+ //Check it is a valid type
+ __ASSERT_DEBUG(!((TInt)ret & ~KNotificationValidFiltersMask) || (ret == EOverflow), Panic(ENotificationPanic));
+ return ret; //Returns the lower 2 bytes of Word2
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The path size should be located at *this + sizeof(NotificationSize)
+ */
+TInt TFsNotification::PathSize() const
+ {
+ //Notification of type EOverflow does not have a path associated with it
+ __ASSERT_DEBUG(NotificationType() != EOverflow,Panic(ENotificationPanic));
+ TUint ret = (*(TUint*)this & 0x0000FFFF); //Returns the lower 2 bytes of Word1
+ return (TInt)ret;
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The path should be located at: *this + KNotificationHeaderSize
+ */
+EXPORT_C TInt TFsNotification::Path(TPtrC& aPath) const
+ {
+ //Notification of type EOverflow does not have a path associated with it
+ if(NotificationType() == EOverflow)
+ return KErrNotSupported;
+
+ TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize);
+ aPath.Set(pathPtr,PathSize()/2);
+ return KErrNone;
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The new name size should be located at: *this + sizeof(NotificationSize) + sizeof(PathSize)
+ */
+TInt TFsNotification::NewNameSize() const
+ {
+ //The only notifications containing a new name are ERename, EVolumeName and EDriveName
+ __ASSERT_DEBUG((NotificationType() == ERename ||
+ NotificationType() == EVolumeName ||
+ NotificationType() == EDriveName),Panic(ENotificationPanic));
+ TInt* word2 = PtrAdd((TInt*)this, sizeof(TInt));
+ return ((*word2) >> 16);
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The new name should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
+ */
+EXPORT_C TInt TFsNotification::NewName(TPtrC& aNewName) const
+ {
+ //Only ERename, EVolumeName and EDriveName have second paths
+ //Notification of type EOverflow does not have a path associated with it
+ TFsNotificationType notificationType = NotificationType();
+ if((notificationType != ERename &&
+ notificationType != EVolumeName &&
+ notificationType != EDriveName) ||
+ notificationType == EOverflow)
+ {
+ return KErrNotSupported;
+ }
+
+ TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize + Align4(PathSize()));
+ aNewName.Set(pathPtr,NewNameSize()/2);
+ return KErrNone;
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The attribute should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
+ */
+EXPORT_C TInt TFsNotification::Attributes(TUint& aSetAtt, TUint& aClearAtt) const
+ {
+ if(NotificationType() != EAttribute)
+ return KErrNotSupported;
+
+ TUint* clearAttptr = PtrAdd((TUint*)this, KNotificationHeaderSize + Align4(PathSize()));
+ aClearAtt = *clearAttptr;
+ aSetAtt = *PtrAdd((TUint*)clearAttptr, sizeof(TUint));
+ return KErrNone;
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID - NOT YET SUPPORTED
+ * Word(s) : Path (TText8) , [Any sub-class members]
+ *
+ * The size should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
+ */
+EXPORT_C TInt TFsNotification::FileSize(TInt64& aSize) const
+ {
+ if(NotificationType() != EFileChange)
+ return KErrNotSupported;
+
+ aSize = *PtrAdd((TInt64*)this, KNotificationHeaderSize + Align4(PathSize()));
+ return KErrNone;
+ }
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID
+ * Word(s) : Path (TText8) , [Any sub-class members]
+
+EXPORT_C TInt TFsNotification::DriveNumber(TInt& aDriveNumber) const
+ {
+ TPtrC path(NULL,0);
+ TInt r = Path(path);
+ if(r == KErrNone)
+ {
+ if(path.Length() >= 2 && ((TChar)path[1]==(TChar)':'))
+ {
+ r = RFs::CharToDrive(path[0],aDriveNumber);
+ }
+ }
+ return r;
+ }
+ */
+
+/*
+ * The order of the data in the buffer is:
+ * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
+ * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
+ * Word3 : UID
+ * Word(s) : Path (TText8) , [Any sub-class members]
+
+EXPORT_C TInt TFsNotification::UID(TUid& aUID) const
+ {
+ TUint* word3 = PtrAdd((TUint*)this, sizeof(TUint)*2);
+ aUID.iUid = *word3;
+ return KErrNone;
+ }
+ */
+
+
+CFsNotificationList* CFsNotificationList::NewL(TInt aBufferSize)
+ {
+ CFsNotificationList* self = new(ELeave) CFsNotificationList;
+ CleanupStack::PushL(self);
+ self->iBuf = HBufC8::NewL(aBufferSize);
+ self->iBufferPtr.Set((TUint8*)self->iBuf->Ptr(),0,self->iBuf->Des().MaxSize());
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CFsNotificationList::CFsNotificationList()
+: iTailPckg(iTail), iBufferPtr(NULL,0)
+ {
+ }
+
+CFsNotificationList::~CFsNotificationList()
+ {
+ delete iBuf;
+ }
+
+TInt CFsNotificationList::BufferSize() const
+ {
+ return iBuf->Size();
+ }
+
+const TFsNotification * CFsNotificationList::NextNotification()
+ {
+ TFsNotification* notification;
+
+ if(iHead == iTail)
+ {
+ return NULL;
+ }
+ TUint* startptr = (TUint*)iBuf->Ptr();
+ TUint* nptr = PtrAdd(startptr, iHead);
+ TInt bufferSize = iBuf->Des().MaxSize();
+ TUint* endOfBuffer = PtrAdd(startptr, bufferSize);
+
+ if(*nptr == KNotificationBufferFiller || nptr == endOfBuffer)
+ {
+ iHead = 0;
+ notification = (TFsNotification*)startptr;
+ }
+ else
+ {
+ notification = (TFsNotification*)nptr;
+ }
+ iHead += notification->NotificationSize();
+ if(iHead == bufferSize)
+ iHead = 0;
+
+ return notification;
+ }
+
+
+EXPORT_C CFsNotify* CFsNotify::NewL(RFs& aFs, TInt aBufferSize)
+ {
+ CFsNotify* self=new(ELeave) CFsNotify;
+ CleanupStack::PushL(self);
+
+ //Making sure buffer size is at least minimally large and not too big
+ if(aBufferSize > (KMaxTInt/2))
+ {
+ User::Leave(KErrArgument);
+ }
+ else if(aBufferSize < KMinNotificationBufferSize)
+ {
+ aBufferSize = KMinNotificationBufferSize;
+ }
+
+ self->ConstructL(aFs, Align4(aBufferSize));
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CFsNotify::ConstructL(RFs& aFs,TInt aBufferSize)
+ {
+ iBody = new(ELeave) CFsNotifyBody();
+ iBody->iBuffer = CFsNotificationList::NewL(aBufferSize);
+ User::LeaveIfError(iBody->iFsNotify.Open(aFs,iBody->iBuffer,iBody->iBufferStatus));
+ }
+
+CFsNotify::CFsNotify()
+ {
+ }
+
+EXPORT_C CFsNotify::~CFsNotify()
+ {
+ if(iBody)
+ {
+ if(iBody->iBuffer)
+ {
+ iBody->iBuffer->iTail = 0;
+ iBody->iBuffer->iHead = 0;
+ iBody->iFsNotify.Close();
+ delete iBody->iBuffer;
+ }
+ }
+ delete iBody;
+ }
+
+CFsNotifyBody::CFsNotifyBody()
+ {
+ }
+
+CFsNotifyBody::~CFsNotifyBody()
+ {
+ }
+
+EXPORT_C TInt CFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename)
+ {
+ if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0))
+ return KErrArgument;
+
+ return iBody->iFsNotify.AddNotification(aNotificationType, aPath, aFilename);
+ }
+
+//Removes notification request, does not close session
+EXPORT_C TInt CFsNotify::RemoveNotifications()
+ {
+ return iBody->iFsNotify.RemoveNotifications();
+ }
+
+EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus& aStatus)
+ {
+ if(aStatus == KRequestPending || ((iBody->iClientStatus != NULL) && (*iBody->iClientStatus == KRequestPending)))
+ return KErrInUse;
+
+ iBody->iClientStatus = &aStatus;
+ //Read the new notifications which will start at tail.
+ //(Also this forbids user access outside permitted range)
+ iBody->iBuffer->iHead = iBody->iBuffer->iTail;
+ iBody->iFsNotify.RequestNotifications(aStatus, iBody->iBuffer->iTailPckg);
+ return KErrNone;
+ }
+
+//Cancels notification request, does not close session
+EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus& aStatus)
+ {
+ if(aStatus != KRequestPending || &aStatus != iBody->iClientStatus)
+ return KErrInUse;
+
+ TInt r = iBody->iFsNotify.CancelNotifications();
+ aStatus = !KRequestPending;
+ iBody->iBuffer->iHead = 0;
+ iBody->iBuffer->iTail = 0;
+ return r;
+ }
+
+EXPORT_C const TFsNotification * CFsNotify::NextNotification()
+ {
+ return iBody->iBuffer->NextNotification();
+ }
+
+
+TInt RFsNotify::Open(RFs& aFs, CFsNotificationList* aBuffer, TRequestStatus& aBufferStatus)
+ {
+ if(aBuffer == NULL || aBuffer->iBuf == NULL || &aFs == NULL || &aBufferStatus==NULL)
+ return KErrArgument;
+
+ TInt err = CreateSubSession(aFs,EFsNotificationOpen);
+ if (err == KErrNone)
+ {
+ aBufferStatus = KRequestPending;
+ //memclr((TUint8*)aBuffer->iBuf->Ptr(),aBuffer->iBuf->Des().MaxSize());
+ SendReceive(EFsNotificationBuffer, TIpcArgs(&aBuffer->iBufferPtr,aBuffer->iBuf->Des().MaxSize()), aBufferStatus);
+ }
+ return err;
+ }
+
+void RFsNotify::Close()
+ {
+ CloseSubSession(EFsNotificationSubClose);
+ }
+
+/*
+[Re]Issues notification request
+Updates buffer, if supplied.
+
+@return - last readable index of buffer.
+*/
+void RFsNotify::RequestNotifications(TRequestStatus& aStatus, TPckg<TInt>& aTailPckg)
+ {
+ aStatus = KRequestPending;
+ SendReceive(EFsNotificationRequest,TIpcArgs(&aTailPckg),aStatus);
+ }
+
+TInt RFsNotify::CancelNotifications()
+ {
+ //there can only be one outstanding notification request at a time
+ return (SendReceive(EFsNotificationCancel));
+ }
+
+//Adds notification filter
+TInt RFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename)
+ {
+ if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0))
+ return KErrArgument;
+
+ return (SendReceive(EFsNotificationAdd,TIpcArgs(aNotificationType,&aPath,&aFilename)));
+ }
+
+//Removes request, does not close session
+TInt RFsNotify::RemoveNotifications()
+ {
+ return(SendReceive(EFsNotificationRemove));
+ }
+#else //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+
+EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const
+ {
+ Panic(ENotificationPanic);
+ return (TFsNotification::TFsNotificationType)0;
+ }
+
+EXPORT_C TInt TFsNotification::Path(TPtrC&) const
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt TFsNotification::NewName(TPtrC&) const
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt TFsNotification::Attributes(TUint&,TUint&) const
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt TFsNotification::FileSize(TInt64&) const
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+/*
+EXPORT_C TInt TFsNotification::DriveNumber(TInt&) const
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt TFsNotification::UID(TUid& aUID) const
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+*/
+
+EXPORT_C CFsNotify* CFsNotify::NewL(RFs& , TInt)
+ {
+ Panic(ENotificationPanic);
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+EXPORT_C CFsNotify::~CFsNotify()
+ {
+ Panic(ENotificationPanic);
+ }
+
+EXPORT_C TInt CFsNotify::AddNotification(TUint, const TDesC&, const TDesC&)
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt CFsNotify::RemoveNotifications()
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus&)
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus&)
+ {
+ Panic(ENotificationPanic);
+ return KErrNotSupported;
+ }
+
+EXPORT_C const TFsNotification * CFsNotify::NextNotification()
+ {
+ Panic(ENotificationPanic);
+ return NULL;
+ }
+
+CFsNotificationList::~CFsNotificationList()
+ {
+ Panic(ENotificationPanic);
+ }
+
+CFsNotifyBody::CFsNotifyBody()
+ {
+ Panic(ENotificationPanic);
+ }
+
+CFsNotifyBody::~CFsNotifyBody()
+ {
+ Panic(ENotificationPanic);
+ }
+
+#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+