--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/openenvcore/backend/src/corebackend/fdesc.cpp Fri Jun 04 16:20:51 2010 +0100
@@ -0,0 +1,1848 @@
+/*
+* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+*/
+
+
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h> // for struct stat
+#include <wchar.h>
+#include <sys/errno.h> // for ENOTSOCK
+#include <sys/ioctl.h>
+#include <c32comm.h>
+#include <sys/stat.h>
+#include <limits.h> //for LLONG_MAX and INT_MAX
+#ifdef SYMBIAN_OE_LIBRT
+#include <sys/shm.h>
+#endif// SYMBIAN_OE_LIBRT
+#include "sysreent.h"
+#include "systemspecialfilercg.h"
+#include "fdesc.h"
+#include "lposix.h"
+#include "ltime.h"
+
+
+
+/*
+Temp directory, this should be checked later
+*/
+#ifdef WIDEP_tmpdir
+#undef WIDEP_tmpdir
+#define WIDEP_tmpdir L"/System/temp/"
+#endif //WIDEP_tmpdir
+
+
+
+CFileDescBase::CFileDescBase( TUint aFcntl, TUint32 aFdAttrib ) :
+ iReadTimeout(-1), iFcntlFlag(aFcntl), iFdAttrib(aFdAttrib), iPollErr(KErrNone)
+ {
+ }
+TInt CFileDescBase::SetAtt(TUint /*aSetAttMask*/, TUint /*aClearAttMask*/)
+ {
+ return 0;
+ }
+
+// A CFileDescBase factory function, for "named" file-like objects
+CFileDescBase* CFileDescBase::Open(const wchar_t* name, int mode, int perms, TInt& err)
+ {
+ err = KErrNone;
+ CFileDescBase* ret = NULL;
+
+ if(WcsCmp(name, L"CON:") == 0)
+ {
+ ret = new CTtyDesc; // NB. This won't be the default stdin/stdout/stderr console
+ }
+ else if(WcsCmp(name, L"NUL:") == 0)
+ {
+ ret = new CFileDescBase;
+ }
+ else if((WcsCmp(name, L"TMP:") == 0) || (mode & O_TMPFILE))
+ {
+ CTempFileDesc* tmp = new CTempFileDesc;
+ if(tmp != NULL)
+ {
+ err = tmp->Open(name, mode);
+ if(err != KErrNone)
+ {
+ delete tmp;
+ tmp = NULL;
+ }
+ }
+ ret = tmp;
+ }
+#ifdef SYMBIAN_OE_LIBRT
+ else if(mode & O_SHMFLG)
+ {
+ CSharedMemDesc* shm= new CSharedMemDesc;
+ if(shm != NULL)
+ {
+ err = shm->Open(name, mode, perms);
+ if(err != KErrNone)
+ {
+ delete shm;
+ shm = NULL;
+ }
+ }
+ ret = shm;
+ }
+ #endif //SYMBIAN_OE_LIBRT
+ else if ((L'C' == name[0]) && (L'O' == name[1]) && (L'M' == name[2]) && (L':' == name[4]) && ((name[3] >= L'1') && (name[3] <= L'9')) ||
+ (L'I' == name[0]) && (L'R' == name[1]) && (L'C' == name[2]) && (L'O' == name[3]) && (L'M' == name[4]) && (L':' == name[6]) && ((name[5] >= L'1') && (name[5] <= L'9')))
+ {
+ CSerialDesc* com = new CSerialDesc;
+ if (com != NULL)
+ {
+ err = com->Open(name, mode, perms);
+ if(err != KErrNone)
+ {
+ delete com;
+ com = NULL;
+ }
+ }
+ ret = com;
+ }
+ else //It's a special file, directory or normal file
+ {
+ RFs& rfs = Backend()->FileSession();
+ TUint attribval;
+ TFullName fullName;
+ err = GetFullFile(fullName, (const TText16*)name, rfs);
+ if(err != KErrNone)
+ return NULL;
+ int ret1 = rfs.Att(fullName, attribval);
+ if (ret1 == 0 && ((attribval & (KEntryAttHidden | KEntryAttSystem))== (KEntryAttHidden | KEntryAttSystem)))
+ {
+ TSpecialFileType fileType = _SystemSpecialFileBasedFilePath(name, err, rfs);
+ if(fileType == EFileTypeMkFifo) //special file, FIFO
+ {
+ ret = CFileTable::FifoOpen(name, mode, perms, err);
+ }
+ else if(fileType == EFileTypeSymLink) //special file, symlink
+ {
+ ret = CFileTable::LinkOpen(name, mode, perms, err, rfs);
+ }
+ }
+ else //normal file or directory
+ {
+ //Try opening as a file
+ CFileDesc* file = new CFileDesc;
+ if(file != NULL)
+ {
+ err = file->Open(rfs, fullName, mode, perms);
+ if(err != KErrNone)
+ {
+ delete file;
+ file = NULL;
+ }
+ }
+ ret = file;
+
+ //Check if it is directory, if the open as file failed
+ if(err != KErrNone && CheckIfDirectory(fullName, rfs))
+ {
+ CDirectoryDesc* dir = new CDirectoryDesc;
+ if(dir != NULL)
+ {
+ err = dir->Open(rfs, fullName, mode, perms);
+ if(err != KErrNone)
+ {
+ delete dir;
+ dir = NULL;
+ }
+ }
+ ret = dir;
+ }
+ }
+ }
+
+ if(err == KErrNone && ret == NULL)
+ {
+ err = KErrNoMemory;
+ }
+
+ return ret;
+ }
+
+//Check if a path corresponds to a directory. This is a helper function
+//for CFileDescBase::Open()
+TBool CFileDescBase::CheckIfDirectory(const TDesC& aPath, RFs& aFs)
+ {
+ //Check whether its a Drive Name
+ if(KMaxDriveName+1 == aPath.Length())
+ {
+ if(RFs::IsValidDrive(TDriveUnit(aPath)))
+ {
+ return ETrue;
+ }
+ }
+ //Now check whether it is a directory
+ else
+ {
+ TEntry entry;
+ if(aFs.Entry(aPath, entry) == KErrNone)
+ {
+ if(entry.IsDir())
+ {
+ return ETrue;
+ }
+ }
+ }
+
+ return EFalse;
+ }
+
+// Useful default implementations for CFileDescBase virtual functions.
+// Function to be re-implemented in a child class which can seek.
+TInt CFileDescBase::LSeek (off_t& offset, int)
+ {
+ // minimal implementation for devices which can't seek
+ offset=-1;
+ return ESPIPE;
+ }
+
+void CFileDescBase::Read (TDes8& aBuf, TRequestStatus& aStatus)
+ {
+ // minimal implementation for /dev/null
+ aBuf.Zero(); // set length to zero
+ TRequestStatus* sp=&aStatus;
+ User::RequestComplete(sp,KErrNone);
+ }
+
+void CFileDescBase::ReadCancel() {}
+
+TInt CFileDescBase::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus)
+ {
+ return aStatus;
+ }
+
+
+TInt CFileDescBase::FStat (struct stat *st)
+ {
+ // minimal implementation:
+ // I am a character device about which little is known
+ st->st_mode = S_IFCHR;
+ st->st_blksize=0;
+ return KErrNone;
+ }
+
+void CFileDescBase::Complete (TRequestStatus& aStatus, TInt aResult)
+ {
+ TRequestStatus* sp=&aStatus;
+ User::RequestComplete(sp,aResult);
+ }
+
+void CFileDescBase::Write (TDes8& /*aBuf*/, TRequestStatus& aStatus)
+ {
+ // minimal implementation for /dev/null
+ // we will claim to have written all of the data
+ Complete(aStatus,KErrNone);
+ }
+
+void CFileDescBase::WriteCancel() {}
+
+TInt CFileDescBase::WriteCompletion (TDes8& /*aBuf*/, TInt aStatus)
+ {
+ return aStatus;
+ }
+
+void CFileDescBase::Sync(TRequestStatus& aStatus)
+ {
+ // minimal implementation for /dev/null
+ Complete(aStatus,KErrNone);
+ }
+
+void CFileDescBase::SyncCancel() {}
+
+void CFileDescBase::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus)
+ {
+ // minimal implementation for /dev/null and other synchronous devices
+ Complete(aStatus,KErrNone);
+ }
+
+void CFileDescBase::IoctlCancel()
+ {
+ return; // suitable for all synchronous ioctls
+ }
+
+TInt CFileDescBase::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
+ {
+ TInt ret=aStatus;
+ if (ret!=KErrNone)
+ return ret;
+ int *param = reinterpret_cast<int*> (aParam);
+ switch ((unsigned)aCmd)
+ {
+ case FIONREAD:
+ case E32IONREAD:
+ *param=0; // claim that no data is available
+ break;
+ case E32IOSELECT:
+ *param=(*param)&(E32SELECT_READ|E32SELECT_WRITE); // but don't block
+ break;
+ default:
+ ret=KErrNotSupported;
+ break;
+ }
+ return ret;
+ }
+
+// A CFileDescBase factory function, for socket objects
+
+CFileDescBase* CFileDescBase::Socket(RSocketServ& aSs, int family, int style, int protocol, TInt& err)
+ {
+ // connect to the Socket Server if necessary
+ if (aSs.Handle()==0)
+ {
+ err=aSs.Connect(TUint(-1)); // allow arbitrary number of requests
+ if (err)
+ return 0;
+ else
+ {
+ err = aSs.ShareAuto();
+ if (err)
+ return 0;
+ }
+ }
+ CSockDescBase *socketBase = NULL;
+ if (family == AF_LOCAL || family == PF_LOCAL || family == AF_UNIX)
+ {
+
+ //coverity[alloc_fn]
+ //coverity[assign]
+
+ socketBase = new CFileSocketDesc;
+ }
+ else
+ {
+ socketBase = new CSocketDesc;
+ }
+
+ if (!socketBase)
+ {
+ err=KErrNoMemory;
+ return 0;
+ }
+ err = socketBase->Socket(aSs,family,style,protocol);
+
+ if (err)
+ {
+ delete socketBase;
+ if (err == KErrBadName) // Some mismatch in family-style-protocol
+ {
+ err = EPROTONOSUPPORT;
+ }
+ //coverity[memory_leak]
+ return 0;
+ }
+ return socketBase;
+ }
+
+// minimal implementation of sockets, useful for all non-socket descriptors
+
+void CFileDescBase::RecvFrom(TDes8& /*aDesc*/, TSockAddr& /*from*/, int /*flags*/, TRequestStatus& aStatus)
+ {
+ // minimal implementation
+ Complete(aStatus,ENOTSOCK);
+ }
+
+void CFileDescBase::RecvFromCancel() {}
+
+TInt CFileDescBase::CompletionStatus (TInt& /*aLength*/, TInt aStatus)
+ {
+ return aStatus;
+ }
+
+void CFileDescBase::SendTo(TDes8& /*aDesc*/, const struct sockaddr* /* anAddr*/, unsigned long /*aAddrLen*/, int /*flags*/, TRequestStatus& aStatus)
+ {
+ // minimal implementation
+ Complete(aStatus,ENOTSOCK);
+ }
+
+void CFileDescBase::SendToCancel() {}
+
+void CFileDescBase::Shutdown(TUint /*aHow*/,TRequestStatus& aStatus)
+ {
+ // minimal implementation
+ Complete(aStatus,ENOTSOCK);
+ }
+
+void CFileDescBase::ShutdownCancel() {}
+
+TInt CFileDescBase::Bind(const struct sockaddr* /*addr*/, unsigned long /*size*/)
+ {
+ return ENOTSOCK;
+ }
+
+TInt CFileDescBase::Listen(TUint /*qSize*/)
+ {
+ return ENOTSOCK;
+ }
+
+void CFileDescBase::Accept(CFileDescBase*& /*aNewSocket*/, TRequestStatus& aStatus, RSocketServ& /*aSs*/, TSockAddr * /*aAddr*/)
+ {
+ // minimal implementation
+ Complete(aStatus,ENOTSOCK);
+ }
+
+void CFileDescBase::AcceptCancel() {}
+
+void CFileDescBase::Connect(const struct sockaddr* /*anAddr*/,unsigned long /*aSize*/,TRequestStatus& aStatus)
+ {
+ // minimal implementation
+ Complete(aStatus,ENOTSOCK);
+ User::WaitForRequest(aStatus);
+ }
+
+void CFileDescBase::ConnectCancel() {}
+
+TBool CFileDescBase::GetConnectionProgress()
+ {
+ return EFalse;
+ }
+
+void CFileDescBase::SetConnectionProgress( TBool /* aInProgress */ ) {}
+
+TInt CFileDescBase::SockName(int /*anEnd*/, struct sockaddr* /*anAddr*/,unsigned long* /*aSize*/)
+ {
+ return ENOTSOCK;
+ }
+
+TInt CFileDescBase::GetSockOpt(TInt /*anOptionName*/,TInt /*anOptionLevel*/,TDes8& /*anOption*/)
+ {
+ return ENOTSOCK;
+ }
+
+TInt CFileDescBase::SetSockOpt(TInt /*anOptionName*/,TInt /*anOptionLevel*/,TDesC8& /*anOption*/)
+ {
+ return ENOTSOCK;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDescBase::Fcntl
+// Minimal Implementation for fcntl
+// -----------------------------------------------------------------------------
+//
+TInt CFileDescBase::Fcntl(TUint /*anArg*/, TUint aCmd)
+ {
+ // minimal implementation:
+ if(aCmd == F_GETFL)
+ {
+ return KErrNotFound;
+ }
+ return KErrNotSupported;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDescBase::Poll
+// Checks the file for ready to write/read and exception status
+// -----------------------------------------------------------------------------
+//
+TInt CFileDescBase::Poll(TPollMode /*aMode*/,TBool& aStatus,TInt& /*aErrno*/)
+ {
+ // always return True, let the derived filedescriptors override
+ aStatus = ETrue;
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDescBase::Poll - Overloaded
+// Synchronous non-blocking call that returns current state of the file descriptor
+// -----------------------------------------------------------------------------
+//
+TInt CFileDescBase::Poll(TUint aEvents)
+ {
+ // We return that the file descriptor is select true for ready to read,
+ // ready to write and error conditions.
+ // Let derived file descriptors override as approp.
+ TInt readyEvents = 0;
+
+ if (aEvents & EReadyForReading)
+ {
+ readyEvents = EReadyForReading;
+ }
+ if (aEvents & EReadyForWriting)
+ {
+ readyEvents |= EReadyForWriting;
+ }
+ if (aEvents & EAnyException)
+ {
+ readyEvents |= EAnyException;
+ }
+
+ return readyEvents;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDescBase::NotifyActivity
+// Registers with the approp. underlying subsystem for read/write/except notifications
+// -----------------------------------------------------------------------------
+//
+TInt CFileDescBase::NotifyActivity(TUint /*aEvents*/, TRequestStatus& /*aRequest*/, TTimeIntervalMicroSeconds32 /*timeout*/)
+ {
+ // We return KErrCompletion indicating that this activity is complete for
+ // this descriptor.
+ // Let derived file descriptors override as approp.
+ return KErrCompletion;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDescBase::TweakWatchedEvents
+// Requests for fd behaviour specific additional events
+// -----------------------------------------------------------------------------
+//
+void CFileDescBase::TweakWatchedEvents(TUint& /*events*/)
+ {
+ // No implementation required
+ // This version is used for both Redir and pipe desc, it is overridden
+ // by socket
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDescBase::TweakReadyEvents
+// Prepares the fd behaviours specific output events
+// -----------------------------------------------------------------------------
+//
+TInt CFileDescBase::TweakReadyEvents(TInt /*errval*/)
+ {
+ return KErrNone;
+ }
+
+// CFileDescBase::CancelNotify
+// Cancel an outstanding request for read/write/except notifications
+// -----------------------------------------------------------------------------
+//
+void CFileDescBase::CancelNotify()
+ {
+ // do nothing
+ return;
+ }
+
+
+// Generic (non-virtual) handling for Close
+EXPORT_C TInt CFileDescBase::Close()
+ {
+ TInt err = KErrNone;
+ //Decrement the dup count and mark this FD as invalid if dupcount is 0
+ if ( --iDupCount < 0 )
+ {
+ iFdAttrib |= KInvalidFd;
+ //delete this FD only if its not mmaped and being used
+ if(!(iFdAttrib & KMMapedFd))
+ {
+ err=FinalClose();
+ //Release the Lock now
+ delete this;
+ }
+ }
+ return err;
+ }
+
+TInt CFileDescBase::FinalClose()
+ {
+ return KErrNone;
+ }
+
+void CFileDescBase::SetFids(void *)
+ {
+ // nada (virtual)
+ }
+
+// Simple implementation of File handling
+static int MapMode(int aMode, TUint& fMode)
+ {
+ // EPOC32 doesn't support Write-Only
+ if (aMode & (O_WRONLY|O_RDWR))
+ {
+ fMode = EFileWrite;
+ }
+ else
+ {
+ fMode = EFileRead;
+ }
+
+ fMode |= (aMode & O_TEXT) ? EFileStreamText : EFileStream;
+ fMode |= EFileShareReadersOrWriters;
+
+ return aMode & (O_CREAT|O_TRUNC|O_APPEND|O_EXCL|O_EXLOCK);
+ }
+
+CFileDesc::CFileDesc()
+ :CFileDescBase(), iSize(EBufferSize), iExt(-1)
+ {}
+
+void CFileDesc::SetState(const TDes& params)
+ {
+ TFileName name;
+ iFile.FullName(name);
+ iDrive = (TInt16)TDriveUnit(name);
+
+ TLex lexr(params);
+ lexr.Val(iPos);
+ lexr.Inc();
+ lexr.Val(iExt);
+ lexr.Inc();
+ lexr.Val(iFcntlFlag);
+ lexr.Inc();
+ lexr.Val(iFdAttrib, EDecimal);
+ lexr.Inc();
+ lexr.Val(iPos);
+ lexr.Inc();
+ lexr.Val(iExt);
+ lexr.Inc();
+ lexr.Val(iSize);
+
+ }
+
+CFileDesc::~CFileDesc()
+ {
+ iFile.Close();
+ if(iBuffer)
+ {
+ RHeap* oldHeap = User::SwitchHeap(Backend()->Heap());
+ delete [] iBuffer;
+ User::SwitchHeap(oldHeap);
+ }
+ }
+
+TInt CFileDesc::FinalClose()
+ {
+ TInt err = DoSync();
+ iLock.Close();
+ return err;
+ }
+
+TInt CFileDesc::Open(RFs& aSession, const TDesC& aName, int mode, int perms)
+ {
+ TInt err;
+ TUint fMode;
+
+ iDrive=(TInt16)TDriveUnit(aName);
+
+ // Create = make new file, can return KErrAlreadyExists
+ // Open = open an existing file, can return KErrPathNotFound or KErrNotFound
+ // Replace = open a new file, zapping the existing one if necessary
+
+ int mapped=MapMode(mode, fMode);
+ // if the file is in \sys, use EFileShareReadersOnly not EFileShareReadersOrWriters
+ TParsePtrC pars(aName);
+ if (pars.Path().FindF(_L("\\SYS\\")) == 0)
+ {
+ fMode &= ~EFileShareReadersOrWriters;
+ fMode |= EFileShareReadersOnly;
+ }
+
+ // if the file is in \resource, dont use EFileShareReadersOrWriters
+ if (pars.Path().FindF(_L("\\resource\\")) == 0)
+ {
+ fMode &= ~EFileShareReadersOrWriters;
+ fMode |= EFileShareReadersOnly;
+ }
+
+ //Set iFcntlFlag flag
+ iFcntlFlag = mode & O_ACCMODE;
+
+ if(mode & O_APPEND)
+ {
+ iFcntlFlag |= O_APPEND;
+ }
+
+ TInt fileMode = 0;
+ TBool created = EFalse;
+ //store the open modes in the file descriptor object
+
+ switch(perms & (S_IRUSR | S_IWUSR ))
+ {
+ case S_IRUSR | S_IWUSR: //owner read write
+ case S_IWUSR : //owner write
+ {
+ break;
+ }
+ case S_IRUSR: //owner read
+ {
+ fileMode = KEntryAttReadOnly;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ switch (mapped)
+ {
+ case O_CREAT|O_EXCL: //For O_EXCL if file exists then return error
+ err = iFile.Create(aSession, aName, fMode);
+ if(err)
+ {
+ return err;
+ }
+ created = ETrue ;
+ break;
+ case O_CREAT|O_TRUNC:
+ err = iFile.Replace(aSession, aName, fMode);
+ if(!err)
+ {
+ created = ETrue;
+ }
+ break;
+ case O_TRUNC:
+ err = iFile.Open(aSession, aName, fMode);
+ if(!err)
+ err = iFile.SetSize(0);
+ break;
+ case O_CREAT|O_EXCL|O_APPEND: //if file exists then return error
+ err = iFile.Create(aSession, aName, fMode);
+ if(err)
+ {
+ return err;
+ }
+ created = ETrue ;
+ break;
+ case O_CREAT|O_EXCL|O_TRUNC: //if file exists then return error
+ err = iFile.Create(aSession, aName, fMode);
+ if(!err)
+ {
+ err = iFile.SetSize(0);
+ created = ETrue ;
+ }
+ else
+ {
+ return err;
+ }
+ break;
+ case O_EXLOCK: //emulating exclusive locks
+ err = iFile.Open(aSession, aName, fMode);
+ if(err == KErrNone)
+ {
+ FSIZE fileSize = 0;
+ err = iFile.Size(fileSize);
+ if(fileSize <= 0 )
+ return KErrNotSupported;
+
+ if(err == KErrNone)
+ {
+ err = iFile.Lock(0, fileSize);
+ }
+ }
+
+ if(err != KErrNone)
+ {
+ return err;
+ }
+ break;
+ // Everything else is assumed to mean open existing file,
+ // If the file isn't there, O_CREAT implies that we should make it
+ default:
+ err = iFile.Open(aSession, aName, fMode);
+ if (err == KErrNotFound && (mapped & O_CREAT))
+ {
+ err = iFile.Create(aSession, aName, fMode);
+ if(!err)
+ {
+ created = ETrue;
+ }
+
+ }
+ if((err == KErrArgument) &&(mode == (O_CREAT | O_RDONLY)))
+ {
+ TUint CrMode = EFileShareReadersOrWriters | EFileWrite ;
+ CrMode |= (mode & O_TEXT) ? EFileStreamText : EFileStream;
+ err = iFile.Create(aSession , aName , CrMode);
+
+ if(!err)
+ {
+ created = ETrue;
+ iFile.Close() ;
+ err = iFile.Open(aSession, aName , fMode);
+ }
+ }
+
+ if (err == KErrNone && (mapped & O_APPEND))
+ {
+ iPos = Ext();
+ if (iPos < 0)
+ err = iPos;
+ }
+ break;
+
+ }
+ if ((mode & O_BUFFERED) == 0)
+ iSize = 0;
+
+ //If File is to be opened for O_CREAT | O_RDONLY, set the corresponding attributes
+ if(created && fileMode)
+ {
+ err = iFile.SetAtt(fileMode, 0) ;
+ }
+
+ if (!err)
+ {
+ err = Alloc();
+ }
+
+ if(err == KErrNone)
+ {
+ err = CreateLock();
+ }
+
+ return err;
+ }
+
+TInt CFileDesc::LSeek (off_t& offset, int whence)
+ {
+ //return if its an invalid fd
+ //This scenario comes when the file is closed, but mmap still exists
+ if(iFdAttrib & KInvalidFd)
+ {
+ return KErrBadHandle;
+ }
+ iLock.Wait();
+ FSIZE pos=offset;
+ FSIZE ext=Ext();
+ if (ext < 0)
+ {
+ iLock.Signal();
+ return ext;
+ }
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ pos += Pos();
+ break;
+ case SEEK_END:
+ pos += ext;
+ break;
+ default:
+ {
+ iLock.Signal();
+ return KErrArgument;
+ }
+ }
+
+ TInt ret = KErrNone;
+ if (pos < 0)
+ {
+ iLock.Signal();
+ return KErrArgument;
+ }
+ else if (pos >= ext)
+ {
+ ret = Flush();
+ if (!ret)
+ {
+ iState = EAlloc;
+ }
+ }
+
+ switch (iState)
+ {
+ case EAlloc:
+ iPos = pos;
+ break;
+ case EReading:
+ {
+ FSIZE lag = iPos - pos;
+ if (lag >= 0 && lag <= (iEnd - iBuffer))
+ iPtr = iEnd - lag;
+ else
+ {
+ iPtr = iEnd;
+ iPos = pos;
+ }
+ }
+ break;
+ case EWriting:
+ if (pos != Pos())
+ {
+ ret = Flush();
+ if (ret != KErrNone)
+ {
+ iLock.Signal();
+ return ret;
+ }
+ iPos = pos;
+ }
+ break;
+ default:
+ {
+ //Do nothing
+ }
+ }
+ offset = pos;
+ iLock.Signal();
+ return ret;
+ }
+
+void CFileDesc::MapStat(struct stat& st, const TTime& aModTime, TUint& aAttr, const mode_t aMode)
+ {
+ if ( aMode == S_IFREG)
+ {
+ st.st_mode = (aAttr&KEntryAttDir) ? S_IFDIR: S_IFREG;
+ }
+ else
+ {
+ st.st_mode = aMode;
+ }
+
+ if ((aAttr&KEntryAttReadOnly))
+ {
+ st.st_mode |= S_IRUSR;
+ }
+ else
+ {
+ st.st_mode = st.st_mode | S_IWUSR | S_IRUSR;
+ }
+
+ st.st_nlink = (S_IFLNK == st.st_mode) ? 2 : 1;
+ TTimeIntervalSeconds res;
+ const TTime KEpocTime(MAKE_TINT64(0x00dcddb3,0x0f2f8000)); // 00:00, Jan 1st 1970
+ if(aModTime.SecondsFrom(KEpocTime, res))
+ {
+ st.st_mtime = -1;
+ st.st_atime = -1 ;
+ st.st_ctime = -1;
+ }
+ else
+ {
+ st.st_mtime = res.Int();
+ st.st_ctime = st.st_atime = st.st_mtime ; //here modification and access time are same
+ }
+ st.st_blksize=512;
+ }
+
+TInt CFileDesc::FStat (struct stat* st)
+ {
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ return KErrBadHandle;
+ }
+ TInt err;
+ TUint att;
+ TTime modtime;
+
+ err = iFile.Att(att);
+ if (!err)
+ {
+ err = iFile.Modified(modtime);
+ if (!err)
+ {
+ FSIZE ext=Ext();
+ if (ext >= 0)
+ {
+ st->st_size = ext;
+ st->st_dev = st->st_rdev = iDrive;
+ MapStat(*st, modtime, att);
+ return 0;
+ }
+ else
+ err = ext;
+ }
+ }
+ return err;
+ }
+
+TInt CFileDesc::SetAtt(TUint aSetAttMask, TUint aClearAttMask)
+ {
+ return iFile.SetAtt(aSetAttMask , aClearAttMask) ;
+ }
+
+TInt CFileDesc::Alloc()
+ {
+ if (iSize)
+ {
+ //Delete if iBuffer is holding some memory already
+ if (iBuffer)
+ {
+ delete [] iBuffer;
+ }
+ iBuffer = new TUint8[iSize];
+ if (iBuffer == 0)
+ return KErrNoMemory;
+ }
+ return KErrNone;
+ }
+
+TInt CFileDesc::FileRead(TUint8* aPtr,TInt aLength)
+ {
+ TPtr8 ptr(aPtr,aLength);
+ TInt r=iFile.Read(iPos,ptr);
+ if (r == KErrNone)
+ {
+ r = ptr.Length();
+ iPos += r;
+ if (r < aLength)
+ iExt = iPos;
+ }
+ return r;
+ }
+
+TInt CFileDesc::FileWrite(TUint8* aPtr,TInt aLength)
+ {
+ TPtrC8 ptr(aPtr,aLength);
+ if (iExt >= 0)
+ {
+ if (iPos > iExt)
+ {
+ iFile.SetSize(iPos);
+ }
+ }
+
+ // Check if the specified file is opened in O_APPEND
+ // mode and set right the file write position
+ if(iFcntlFlag & O_APPEND)
+ {
+ FSIZE bytes=0;
+ TInt ret = iFile.Size(bytes);
+ if (ret < 0)
+ return ret;
+ iPos = Max(bytes, Pos());
+ }
+
+ TInt r = iFile.Write(iPos,ptr);
+ if (r == KErrNone)
+ {
+ r = ptr.Length();
+ iPos += aLength;
+ if (iPos > iExt && iExt >= 0)
+ iExt = iPos;
+ }
+ return r;
+ }
+
+TInt CFileDesc::Flush()
+ {
+ if (iPtr > iBuffer)
+ {
+ TInt r = FileWrite(iBuffer, iPtr-iBuffer);
+ if (r < 0)
+ return r;
+ iPtr = iBuffer;
+ }
+ return KErrNone;
+ }
+
+TInt CFileDesc::DoRead (TDes8& aDesc)
+ {
+ if (iState != EReading)
+ {
+ if (iState != EAlloc)
+ {
+ TInt ret = Flush();
+ if (ret != KErrNone)
+ {
+ return ret;
+ }
+ }
+ iState = EReading;
+ iPtr = iEnd = iBuffer;
+ }
+
+ TUint8* p = (TUint8*) aDesc.Ptr();
+ TInt max = aDesc.MaxLength();
+ TInt avail = iEnd - iPtr;
+ TInt len = Min(max, avail);
+ if (len > 0)
+ {
+ p = Mem::Copy(p, iPtr, len);
+ iPtr += len;
+ max -= len;
+ }
+ if (max >= iSize)
+ {
+ TInt ret = FileRead(p, max);
+ if (ret < 0)
+ return ret;
+ p += ret;
+ }
+ else if (max > 0)
+ {
+ TInt ret = FileRead(iBuffer, Min(max + EReadAhead, iSize));
+ if (ret < 0)
+ return ret;
+ len = Min(max, ret);
+ p = Mem::Copy(p, iBuffer, len);
+ iPtr = iBuffer + len;
+ iEnd = iBuffer + ret;
+ }
+ aDesc.SetLength(p-aDesc.Ptr());
+ return aDesc.Length();
+ }
+
+void CFileDesc::Read (TDes8& aDesc, TRequestStatus& aStatus)
+ {
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ Complete(aStatus, KErrBadHandle);
+ return;
+ }
+ //Acquire the Lock before read and release it later
+ iLock.Wait();
+ Complete(aStatus,DoRead(aDesc));
+ iLock.Signal();
+ }
+
+TInt CFileDesc::DoWrite (TDes8& aDesc)
+ {
+ if (iState != EWriting)
+ {
+ if (iState != EAlloc)
+ {
+ iPos -= iEnd - iPtr;
+ }
+
+ iState = EWriting;
+ iPtr = iBuffer;
+ iEnd = iBuffer + iSize;
+ }
+
+ TUint8* p = (TUint8*) aDesc.Ptr();
+ TInt max = aDesc.Length();
+ TInt avail = iEnd - iPtr;
+ TInt len = Min(max, avail);
+ if (len > 0)
+ {
+ iPtr = Mem::Copy(iPtr, p, len);
+ p += len;
+ max -= len;
+ }
+ if (max == 0)
+ return len;
+ TInt r=Flush();
+ if (r < 0)
+ return r;
+ if (max >= iSize)
+ return len + FileWrite(p, max);
+ iPtr = Mem::Copy(iPtr, p, max);
+ return len + max;
+ }
+
+void CFileDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
+ {
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ Complete(aStatus, KErrBadHandle);
+ return;
+ }
+ //Acquire the Lock before write and release it later
+ iLock.Wait();
+ Complete(aStatus,DoWrite(aDesc));
+ iLock.Signal();
+ }
+
+TInt CFileDesc::DoSync()
+ {
+ if (iState == EWriting)
+ {
+ TInt ret = Flush();
+ if (ret < 0)
+ return ret;
+ }
+ return iFile.Flush();
+ }
+
+void CFileDesc::Sync(TRequestStatus& aStatus)
+ {
+ iLock.Wait();
+ Complete(aStatus,DoSync());
+ iLock.Signal();
+ }
+
+FSIZE CFileDesc::Pos()
+ {
+ FSIZE pos = iPos;
+ if (iState == EReading)
+ pos -= (iEnd - iPtr);
+ else if (iState == EWriting)
+ pos += (iPtr - iBuffer);
+ return pos;
+ }
+
+FSIZE CFileDesc::Ext()
+ {
+ TInt r = iFile.Size(iExt);
+ if (r < 0)
+ return r;
+ return iExt;
+ }
+
+TInt CFileDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
+ {
+ TInt ret=aStatus;
+ if (ret!=KErrNone)
+ return ret;
+ // some useful sums about the current state of the file
+ FSIZE curoff = Pos();
+ FSIZE size = Ext();
+ if (size < 0)
+ ret = size;
+ int *param=reinterpret_cast<int*> (aParam);
+ switch ((unsigned)aCmd)
+ {
+ case FIONREAD:
+ case E32IONREAD:
+ if (ret==KErrNone)
+ *param=(size-curoff);
+ break;
+ case E32IOSELECT:
+ {
+ int mask=E32SELECT_WRITE;
+ if ((size-curoff)>0)
+ mask |= E32SELECT_READ;
+ *param=(*param)&mask; // but don't block
+ }
+ break;
+ default:
+ ret=KErrNotSupported;
+ break;
+ }
+ return ret;
+ }
+
+
+#if defined(SYMBIAN_OE_LARGE_FILE_SUPPORT) && !defined(SYMBIAN_OE_NO_LFS)
+// this needs to be corrected once the api which gives the large file size is available.
+//#define MAX_SIZE LLONG_MAX /* 2^63-1 - MAX file size */
+#define MAX_SIZE INT_MAX /* 2^31-1 - MAX file size */
+#else
+#define MAX_SIZE INT_MAX /* 2^31-1 - MAX file size */
+#endif //SYMBIAN_OE_LARGE_FILE_SUPPORT && !SYMBIAN_OE_NO_LFS
+
+TInt CFileDesc::ProcessLockParams(FSIZE& pos, FSIZE& lock_len, TInt& lock_type, struct flock* lock)
+ {
+ TInt retVal=0;
+ lock_type = lock->l_type;
+ if(!lock->l_len) //if len = 0 then lock must be extended to the system limit for max file size
+ {
+ lock_len=MAX_SIZE;
+ }
+ else //len argument is non-zero
+ {
+ lock_len = lock->l_len;
+ }
+ pos =lock->l_start; //offset
+ switch( lock->l_whence )
+ {
+ case SEEK_SET:
+
+ if(pos<0)
+ {
+ retVal = KErrArgument;
+ return retVal;
+ }
+ else
+ break;
+ case SEEK_CUR:
+ pos += iPos; //current position + offset
+ break;
+ case SEEK_END:
+ retVal = iFile.Size(pos);
+ switch( retVal)
+ {
+ case KErrNone:
+ pos += lock->l_start; //file size + ofset
+ break;
+ default:
+ return retVal;
+ }
+
+ if(pos<0)
+ {
+ retVal = KErrArgument;
+ return retVal;
+ }
+ break;
+ default:
+ retVal = KErrArgument; //invalid argument
+ return retVal;
+ }
+
+ if( lock_len < 0)
+ {
+ pos += lock_len;
+ lock_len = -lock_len;
+ }
+ return retVal;
+ }
+// -----------------------------------------------------------------------------
+// CFileDesc::Fcntl
+// Symbian File Specific Implementation for fcntl
+// There is no mapping from Symbian RFile for File fcntl.
+// This implementation supports fcntl with F_SETFL and F_GETFL as cmd
+// We can set the Flag as Blocking or Non-Blocking.
+// -----------------------------------------------------------------------------
+//
+TInt CFileDesc::Fcntl(TUint anArg, TUint aCmd)
+ {
+ struct flock *lock = NULL;
+ FSIZE pos = 0,lock_len = -1;
+ TInt lock_type = -1;
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ return KErrBadHandle;
+ }
+ TInt retVal = KErrNone;
+ //fcntl supports only F_SETFL and F_GETFL for Non-Blocking I/O
+ //If aCmd and anArg does not match these, return with Error
+ switch( aCmd )
+ {
+ case F_SETFL:
+ {
+ //Set the fcntl Flag
+ if((anArg == O_APPEND) || (anArg == O_NONBLOCK))
+ {
+ iFcntlFlag |= anArg ;
+ }
+ retVal = 0 ;
+ break;
+ }
+ case F_GETFL:
+ {
+ //Return fcntl flag
+ retVal = iFcntlFlag;
+ break;
+ }
+ case F_GETFD:
+ {
+ if(iFdAttrib & KCloseonExec)
+ {
+ retVal = 1;
+ }
+ break;
+ }
+ case F_SETFD:
+ {
+ if(anArg == 1)
+ {
+ iFdAttrib |= SET_CLOSE_ON_EXEC_FLG; // (1 << 2) ;
+ retVal = anArg;
+ }
+ else if(anArg == 0 )
+ {
+ iFdAttrib &= ~SET_CLOSE_ON_EXEC_FLG; //(1 << 2) ;
+ retVal = anArg;
+ }
+ else
+ {
+ retVal = KErrArgument; //return invalid argument
+ }
+ break;
+ }
+ case F_GETLK:
+ {
+ lock = (struct flock*)anArg;
+ retVal=ProcessLockParams(pos, lock_len, lock_type, lock);
+ if(retVal)
+ return retVal;
+ switch( lock_type)
+ {
+ case F_WRLCK:
+ retVal = iFile.Lock(pos ,lock_len); //try to lock the region.
+ if (retVal == KErrNone)
+ {
+ retVal = iFile.UnLock(pos ,lock_len); //if previous lock() is successful then unlock the region
+ lock->l_type = F_UNLCK; //indication that region can be locked
+ }
+ else
+ {
+ retVal = KErrNone; //region cant be lock. return success, but don't change lock->l_type
+ }
+ break;
+ default:
+ retVal = KErrArgument;
+ }
+ break;
+ }
+ case F_SETLK:
+ {
+ lock = (struct flock*)anArg;
+ retVal=ProcessLockParams(pos, lock_len, lock_type, lock);
+ if(retVal)
+ return retVal;
+ switch( lock_type)
+ {
+ case F_WRLCK:
+ retVal = iFile.Lock(pos ,lock_len); //try to lock without waiting
+ break;
+ case F_UNLCK:
+ retVal = iFile.UnLock(pos ,lock_len); //try to unlock without waiting
+ break;
+ case F_RDLCK:
+ retVal = KErrNotSupported;
+
+ default:
+ retVal = KErrArgument; //return invalid argument
+ }
+ break;
+ }
+ default:
+ retVal = KErrNotSupported;
+ }
+ return retVal;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileDesc::Truncate
+// Symbian File Specific Implementation for Truncate
+// This will truncate the file which is opened in write mode
+// -----------------------------------------------------------------------------
+//
+TInt CFileDesc::Truncate(off_t anOffset)
+ {
+ TInt retVal;
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ return KErrBadHandle;
+ }
+ iExt = anOffset;
+ retVal = iFile.SetSize(anOffset);
+ if (retVal == KErrNotSupported)
+ {
+ return KErrArgument;//to work around RFile64::SetSize() return value
+ }
+ return retVal;
+ }
+
+// Extra support for temporary files
+TInt CTempFileDesc::Open(const wchar_t* aName, TInt mode)
+ {
+ iSession = Backend()->FileSession();
+
+ TFileName filePath;
+ if (mode & O_TMPFILE) //from tmpfile()
+ {
+ //obtain original mode for tmpfile()
+ mode &= (~O_TMPFILE);
+ filePath.Copy((const TText*)aName);
+ }
+ else //for "TMP:"
+ {
+ TParse path;
+ TInt err = GetFullPath(path, (const TText16*)WIDEP_tmpdir, NULL);
+ if (err != KErrNone)
+ {
+ return err;
+ }
+ filePath.Copy(path.DriveAndPath());
+ }
+
+ if((mode & O_BUFFERED) == 0)
+ {
+ setSize(0);
+ }
+ iFcntlFlag = mode & O_ACCMODE;//setting the fcntl flag
+ TInt ret = Alloc();
+ if (ret != KErrNone)
+ {
+ return ret;
+ }
+ TFileName aPathName;
+ aPathName.Append(iSession.GetSystemDriveChar());
+ aPathName.Append(TChar(KDriveDelimiter));
+ aPathName.Append(_L("\\System\\temp"));
+ if (filePath.Find(aPathName) == 0)
+ {
+ ret = iSession.MkDir(filePath);
+ if (ret != KErrNone && ret != KErrAlreadyExists)
+ {
+ return ret;
+ }
+ else
+ {
+ ret = iFile.Temp(iSession, filePath, iName, EFileShareReadersOrWriters);
+ }
+ }
+ else
+ {
+ ret = iFile.Create(iSession, filePath, EFileShareReadersOrWriters);
+ }
+ return ret;
+ }
+
+TInt CTempFileDesc::FinalClose()
+ {
+ TInt ret = iFile.FullName(iName);
+ if (ret != KErrNone)
+ {
+ return ret;
+ }
+ iFile.Close();
+ return iSession.Delete(iName);
+ }
+
+#ifdef SYMBIAN_OE_LIBRT
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::CSharedMemDesc : Constructor
+// Constructs sharedmemory Descriptor
+// -----------------------------------------------------------------------------
+CSharedMemDesc::CSharedMemDesc()
+ {
+ iLock.CreateLocal();
+ }
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::CSharedMemDesc : Destructor
+// Destructor for sharedmemory Descriptor
+// -----------------------------------------------------------------------------
+CSharedMemDesc::~CSharedMemDesc()
+ {
+ iLock.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::Open
+// Gives sharedmemory Descriptor
+// -----------------------------------------------------------------------------
+TInt CSharedMemDesc::Open(const wchar_t* aName, int mode, int perms)
+ {
+ int aerr = 0, err =0;
+ void* ptr = NULL;
+ TInt shmkey = 0;
+ TInt shmid = 0;
+ struct shmid_ds *buf = NULL;
+
+ mode &= (~O_SHMFLG);
+ if(mode == O_WRONLY)
+ {
+ return KErrNone;
+ }
+
+ TFileName shrdmemname;
+ shrdmemname.Copy((const TText*)aName);
+
+ iPerms = perms;
+ iFcntlFlag = mode & O_ACCMODE;
+ shmkey = GeneratePathKey(shrdmemname);
+ switch (mode)
+ {
+ case O_CREAT:
+ case O_CREAT|O_RDWR:
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, IPC_CREAT|perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ break;
+ case O_TRUNC:
+ case O_TRUNC|O_RDWR:
+ case O_CREAT|O_TRUNC:
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, IPC_CREAT|perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ if (Backend()->iIpcS.shmctl(shmid, IPC_RMID, buf, aerr) == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, IPC_CREAT|perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ break;
+ case O_CREAT|O_EXCL:
+ case O_CREAT|O_EXCL|O_RDWR:
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, IPC_CREAT|IPC_EXCL|perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ break;
+ case O_CREAT|O_EXCL|O_TRUNC:
+ case O_CREAT|O_EXCL|O_TRUNC|O_RDWR:
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, IPC_CREAT|IPC_EXCL|perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ if (Backend()->iIpcS.shmctl(shmid, IPC_RMID, buf, aerr) == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, IPC_CREAT|IPC_EXCL|perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ break;
+ default:
+ shmid = Backend()->iIpcS.shmget(shmkey, SHM_CHUNKSIZE, perms, aerr);
+ if (shmid == -1)
+ {
+ err = aerr;
+ return err;
+ }
+ break;
+ }
+ ptr = Backend()->iIpcS.shmat(shmid, (void *)NULL, 0, aerr);
+ if (ptr == (void*)-1)
+ {
+ err = aerr;
+ return err;
+ }
+ iPtr = ptr;
+ iKey = shmkey;
+ return err;
+ }
+
+TInt CSharedMemDesc::ShmRead(TUint8* aPtr,TInt aLength)
+ {
+ TInt err = KErrNone;
+ iSize = Backend()->iIpcS.GetShmSize(iKey, err);
+ TInt diff = iSize - iPos;
+ if (aLength >= diff)
+ aLength = diff;
+ TPtr8 ptr(aPtr, aLength);
+ ptr.Copy((TUint8*)(iPtr)+iPos, aLength);
+ TInt r = ptr.Length();
+ iPos += r;
+ return r;
+ }
+
+TInt CSharedMemDesc::DoShmRead (TDes8& aDesc)
+ {
+ TUint8* p = (TUint8*) aDesc.Ptr();
+ TInt max = aDesc.MaxLength();
+ TInt ret = ShmRead(p, max);
+ p += ret;
+ aDesc.SetLength(p-aDesc.Ptr());
+ return aDesc.Length();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::Read
+// Reading from a sharedmemory
+// -----------------------------------------------------------------------------
+void CSharedMemDesc::Read(TDes8& aDesc, TRequestStatus& aStatus)
+ {
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ Complete(aStatus, KErrBadHandle);
+ return;
+ }
+ //Acquire the Lock before read and release it later
+ iLock.Wait();
+ Complete(aStatus,DoShmRead(aDesc));
+ iLock.Signal();
+ }
+
+TInt CSharedMemDesc::ShmWrite(TUint8* aPtr,TInt aLength)
+ {
+ TInt err = KErrNone;
+ TInt size = Backend()->iIpcS.GetShmSize(iKey, err);
+ TPtrC8 ptr(aPtr,aLength);
+ TUint8* bufPtr = const_cast<TUint8*>(ptr.Ptr());
+ TInt len = ptr.Length();
+ TInt r = Min(aLength, len);
+ Mem::Copy((TUint8*)(iPtr)+iPos, bufPtr, r);
+ iPos += r;
+ if (iPos > iExt && iExt >= 0)
+ iExt = iPos;
+ if (iExt <= size)
+ iSize = iExt = size;
+ else
+ iSize = iExt;
+ Backend()->iIpcS.SetShmSize(iKey, iSize, err);
+ return r;
+ }
+
+TInt CSharedMemDesc::DoShmWrite (TDes8& aDesc)
+ {
+ TUint8* p = (TUint8*) aDesc.Ptr();
+ TInt max = aDesc.Length();
+ return ShmWrite(p, max);
+ }
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::Write
+// Writing to sharedmemory
+// -----------------------------------------------------------------------------
+void CSharedMemDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
+ {
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ Complete(aStatus, KErrBadHandle);
+ return;
+ }
+ //Acquire the Lock before write and release it later
+ iLock.Wait();
+ Complete(aStatus,DoShmWrite(aDesc));
+ iLock.Signal();
+ }
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::Fcntl
+// fcntl Implementation for sharedmemory
+// -----------------------------------------------------------------------------
+//
+TInt CSharedMemDesc::Fcntl(TUint anArg, TUint aCmd)
+ {
+ //return if its an invalid fd
+ if(iFdAttrib & KInvalidFd)
+ {
+ return KErrBadHandle;
+ }
+ TInt retVal = KErrNotSupported;
+ //fcntl supports only F_SETFL and F_GETFL for Non-Blocking I/O
+ //If aCmd and anArg does not match these, return with Error
+ switch(aCmd)
+ {
+ case F_SETFL:
+ {
+ //Set the fcntl Flag
+ if(anArg == O_NONBLOCK)
+ {
+ iFcntlFlag |= anArg ;
+ }
+ retVal = 0 ;
+ break;
+ }
+ case F_GETFL:
+ {
+ //Return fcntl flag
+ retVal = iFcntlFlag;
+ break;
+ }
+ case F_GETFD:
+ {
+ if(iFdAttrib & KCloseonExec)
+ {
+ retVal = 1;
+ }
+ break;
+ }
+ case F_SETFD:
+ {
+ if(anArg == 1)
+ {
+ iFdAttrib |= SET_CLOSE_ON_EXEC_FLG; // (1 << 2) ;
+ retVal = anArg;
+ }
+ else if(anArg == 0 )
+ {
+ iFdAttrib &= ~SET_CLOSE_ON_EXEC_FLG; //(1 << 2) ;
+ retVal = anArg;
+ }
+ else
+ {
+ retVal = KErrArgument; //return invalid argument
+ }
+ break;
+ }
+ }
+ return retVal;
+ }
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::FStat
+// stat Implementation for sharedmemory
+// -----------------------------------------------------------------------------
+//
+TInt CSharedMemDesc::FStat(struct stat *st)
+ {
+ // set mode as directory
+ TInt err = 0, aerr =0;
+ TInt shmid = 0;
+ struct shmid_ds shmDesc;
+ st->st_mode = S_IFREG|iPerms;
+ shmid = Backend()->iIpcS.shmget(iKey, SHM_CHUNKSIZE, iPerms, aerr);
+ Backend()->iIpcS.shmctl(shmid, IPC_STAT, &shmDesc, aerr);
+ st->st_uid = shmDesc.shm_perm.cuid;
+ st->st_gid = 0;
+ st->st_size = Backend()->iIpcS.GetShmSize(iKey, err);
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CSharedMemDesc::FinalClose
+// stat Implementation for sharedmemory
+// -----------------------------------------------------------------------------
+//
+TInt CSharedMemDesc::FinalClose()
+ {
+ TInt err = 0;
+ TInt ret = KErrNone;
+ ret = Backend()->iIpcS.shmdt(iPtr, err);
+ iLock.Close();
+ return ret;
+ }
+
+TInt CSharedMemDesc::Pos()
+ {
+ return iPos;
+ }
+
+TInt CSharedMemDesc::Ext()
+ {
+ return iExt;
+ }
+
+//-------------------------------------------------------------------------------
+// Function Name : CSharedMemDesc::LSeek()
+// Description : Shall seek to specific position of shared memory
+//-------------------------------------------------------------------------------
+TInt CSharedMemDesc::LSeek (off_t& offset, int whence)
+ {
+ //return if its an invalid fd
+ //This scenario comes when the file is closed, but mmap still exists
+ if(iFdAttrib & KInvalidFd)
+ {
+ return KErrBadHandle;
+ }
+ TInt pos=offset;
+ TInt ext=Ext();
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ pos += Pos();
+ break;
+ case SEEK_END:
+ pos += ext;
+ break;
+ default:
+ return KErrArgument;
+ }
+ if (pos < 0)
+ {
+ return KErrArgument;
+ }
+ iPos = pos;
+ offset = pos;
+ return KErrNone;
+ }
+
+#endif //SYMBIAN_OE_LIBRT
+