--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/openenvcore/backend/src/corebackend/localif.cpp Fri Jun 04 16:20:51 2010 +0100
@@ -0,0 +1,4108 @@
+/*
+* Copyright (c) 1999-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 <fcntl.h>
+#include <sys/errno.h>
+#include <sys/serial.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/syslimits.h>
+#include <utf.h>
+#include "sysreent.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "sysif.h"
+#include "fdesc.h"
+#include "ltime.h"
+#include "lposix.h"
+#include "systemspecialfilercg.h"
+#include "link.h"
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+#include <stdlib.h>
+#include <signal.h>
+#include "tsignalmessage.h"
+#endif // SYMBIAN_OE_POSIX_SIGNALS
+
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+#define SIG_SIGNAL_PRESENT_IN_SIGSET(sig,set) ((set & (1ULL << (sig-1))) != 0x0000000000000000ULL)
+#define SIG_ISEMPTY_SIGSET(set) (set == 0x0000000000000000ULL)
+#define SIG_EMPTY_SIGSET(set) {set = 0x0000000000000000ULL;}
+#define SIG_FILL_SIGSET(set) {set = 0xFFFFFFFFFFFFFFFFULL;}
+#define SIG_ADD_SIGNAL_TO_SET(sig,set) {set |= (1ULL << (sig-1));}
+#define SIG_REMOVE_SIGNAL_FROM_SET(sig,set) {set &= ~(1ULL << (sig-1));}
+
+static void sig_exit();
+
+const TUint KSignalPipeSize = 1024;
+#endif
+
+
+#ifdef __WINSCW__
+#include <pls.h> // For emulator WSD API
+const TUid KBackendUid3 = {0x102828D5};
+#elif defined __X86GCC__
+// GCC compiler generates an undefined reference error if static CLocalSystemInterface object is created in a local function. Therefore give it global scope on this platform.
+CLocalSystemInterface TheBackend;
+#elif defined __EPOC32__
+//Globally declaring the CLSI object to overcome the DCLP implementation if given a static scope.
+CLocalSystemInterface backend;
+#endif
+
+const TUint KConvertToMicroSecond = 1000000;
+
+// Create static singleton backend object for the Process and return the same
+EXPORT_C CLocalSystemInterface* Backend()
+ {
+#ifdef __WINSCW__
+ // Access the PLS of this process
+ CLocalSystemInterface* backend = Pls<CLocalSystemInterface>(KBackendUid3);
+ return backend;
+#elif defined __X86GCC__
+ return &TheBackend;
+#else
+ return &backend;
+#endif
+ }
+
+// Construction of Backend Object which is going to be singleton object for the process
+EXPORT_C CLocalSystemInterface::CLocalSystemInterface() : iOpenDirList(CLocalSystemInterface::KDirGran),
+iTLDInfoList(CLocalSystemInterface::KTLDInfoListGran)
+ {
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+ iSignalsInitialized = EFalse;
+ iSigInitWaitCount = 0;
+ iSigInitWaitMutex.CreateLocal();
+ iSigInitWaitSemaphore.CreateLocal(0);
+ iBlockedSAMutex.CreateLocal();
+ iSignalWaiterMutex.CreateLocal();
+ iSignalInitSemaphore.CreateLocal(0);
+#endif
+ //Create the Heap for all the libraries (local to this process)
+ const TInt KMaxHeapSize = 1048576 ; // 1MB
+ iPrivateHeap = UserHeap::ChunkHeap(NULL, KMinHeapSize, KMaxHeapSize);
+ if (!iPrivateHeap)
+ {
+ User::Panic(KEstlibInit, KErrNoMemory);
+ }
+
+ // Switch to the backend private heap
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+
+ TInt err = iFids.Init(iPrivateHeap);
+ if ( !err )
+ {
+ CRedirDesc* redirMedia = new CRedirDesc();
+ if (redirMedia)
+ {
+ CStdErrDesc* errMedia = new CStdErrDesc();
+ if(errMedia)
+ {
+ iFids.Default(redirMedia, errMedia);
+ redirMedia->Close();
+ errMedia->Close();
+ }
+ else
+ {
+ iPrivateHeap->Free(redirMedia);
+ }
+ }
+ }
+#if (defined SYMBIAN_OE_POSIX_SIGNALS && defined SYMBIAN_OE_LIBRT)
+ iTimerOverrunsMutex.CreateLocal(); //use backend heap
+#endif
+
+ // Reset to the thread's default heap
+ User::SwitchHeap(oldHeap);
+
+ if (!err)
+ {
+ err=iFs.Connect();
+ if(!err)
+ {
+ err = iFs.ShareAuto();
+ }
+ }
+
+ if (!err)
+ {
+ err = PosixFilesystem::SetDefaultDir(iFs);
+ }
+
+ //Cache the session path to avoid querying RFs every time it is needed
+ if(err == KErrNone)
+ {
+ err = iFs.SessionPath(iSessionPath);
+ }
+
+
+ if(err == KErrNone)
+ {
+ //Create Server Locks
+ err |= iSSLock.CreateLocal();
+ err |= iCSLock.CreateLocal();
+ err |= iIpcS.iLock.CreateLocal();
+ //Create TLDList Lock
+ err |= iTLDListLock.CreateLocal();
+ //Create the lock for Session Path
+ err |= iSessionPathLock.CreateLocal();
+ //Lock for protecting iASelectRequest across threads
+ err |= iASelectLock.CreateLocal();
+ //Protect the iDefConnection from concurrent GetDefaultConnection calls
+ err |= iDefConnLock.CreateLocal();
+ }
+
+ if(err == KErrNone)
+ {
+ err = iTzServer.Connect();
+ if(!err)
+ {
+ err = iTzServer.ShareAuto();
+ }
+ }
+
+
+ //Panic if any of the above operation returns with error
+ if (err)
+ {
+ User::Panic(KEstlibInit, err);
+ }
+
+ iCleanup.StorePtrs(iPrivateHeap, &iFs, &iSs, &iCs, &iSSLock, &iCSLock, &iTzServer);
+
+ // No connection settings by default
+ iDefConnPref = NULL;
+ }
+
+EXPORT_C CLocalSystemInterface::~CLocalSystemInterface()
+//
+// Shut down all server connections in use
+//
+ {
+ iTLDListLock.Close();
+ iSessionPathLock.Close();
+ // Close the aselect lock
+ iASelectLock.Close();
+ // Close the default connection lock
+ iDefConnLock.Close();
+ //close the default RConnection
+ if(iDefConnection.SubSessionHandle() != 0)
+ iDefConnection.Close();
+
+ RHeap* oHeap = User::SwitchHeap(iPrivateHeap);
+ for (TInt i = 0, count = iTLDInfoList.Count(); i < count; i++ )
+ {
+ iTLDInfoList[i].Close(iPrivateHeap);
+ }
+
+ // close the RArray itself
+ iTLDInfoList.Close();
+ // Cleanup the threads serving aselect requests
+ int err;
+ // passing 1 to cancelaselect will kill all the threads serving aselect
+ cancelaselect(NULL,err,1);
+ // Switch to backend heap
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ // Close the array that maintains aselect request details
+ iASelectRequest.Close();
+ //close the RTz server
+ iTzServer.Close();
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+
+ if( iDefConnPref )
+ {
+ switch( iDefConnPref->ExtensionId() )
+ {
+ case TConnPref::EConnPrefSnap:
+ {
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ delete (TCommSnapPref*)iDefConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ iDefConnPref = NULL;
+ }
+ break;
+
+ case TConnPref::EConnPrefCommDb:
+ {
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ delete (TCommDbConnPref*)iDefConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ iDefConnPref = NULL;
+ }
+ break;
+
+ default:
+ {
+ // Unknown type of Connection Pref, do nothing
+ }
+ }
+ }
+
+#if (defined SYMBIAN_OE_POSIX_SIGNALS && defined SYMBIAN_OE_LIBRT)
+ iTimerOverrunsMutex.Close();
+ iTimerOverruns.Close();
+#endif
+ //close the RpointerArray
+ iOpenDirList.Close();
+ User::SwitchHeap(oHeap);
+ }
+
+#ifdef __SYMBIAN_COMPILE_UNUSED__
+CLocalSystemInterface& CLocalSystemInterface::Clone()
+ {
+ return *this;
+ }
+
+void CLocalSystemInterface::Release()
+ {
+ // nada. TODO: Remove this method
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::TerminateProcess
+// Sends a message to Posix Server to Terminate itself!
+// And delete the Process (self)
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::TerminateProcess(int status)
+ {
+ //delete this;
+ RProcess().Terminate(status);
+ }
+#endif //__SYMBIAN_COMPILE_UNUSED__
+
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::Exit
+// Close all the open FIDS,Terminate the process
+//
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::Exit(int code)
+ {
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+ TRequestStatus status = KRequestPending;
+ iSignalHandlerThread.Logon(status);
+ iSignalLoopRunning = EFalse;
+ iSignalHandlerThread.RequestSignal();
+ User::WaitForRequest(status);
+#endif
+ iFids.Close();
+ User::SetCritical(User::EProcessPermanent);
+ User::Exit(code);
+ }
+
+// Simple layer over PosixFilesystem
+
+wchar_t * CLocalSystemInterface::getcwd (wchar_t* buf, unsigned long len, int& anErrno)
+ {
+ return PosixFilesystem::getcwd(iFs, buf, len, anErrno);
+ }
+
+int CLocalSystemInterface::chdir (const wchar_t* aPath, int& anErrno)
+ {
+ return PosixFilesystem::chdir(iFs, aPath, anErrno);
+ }
+
+int CLocalSystemInterface::rmdir (const wchar_t* aPath, int& anErrno)
+ {
+ return PosixFilesystem::rmdir(iFs, aPath, anErrno);
+ }
+
+int CLocalSystemInterface::mkdir (const wchar_t* aPath, int perms, int& anErrno)
+ {
+ return PosixFilesystem::mkdir(iFs, aPath, perms, anErrno);
+ }
+
+int CLocalSystemInterface::stat (const wchar_t* name, struct stat *st, int& anErrno)
+ {
+ const wchar_t* filename;
+ // This needs to be zero terminated
+ TBuf<KMaxFileName> inputName;
+ TUint pathAtt = 0;
+ TInt err = GetFullFile(inputName,(const TText16*)name,iFs);
+ if( !err )
+ {
+ TInt err = iFs.Att(inputName,pathAtt);
+ if ( (err == KErrNone) && (pathAtt & KEntryAttDir) )
+ {
+ inputName.Append(_L("\\"));
+ }
+ filename = (wchar_t*)inputName.PtrZ();
+ }
+ // try to stat anyway
+ else
+ {
+ inputName.Copy((const TText16*)name);
+ filename = (wchar_t*)inputName.PtrZ();
+ }
+ TSpecialFileType fileType;
+ struct SLinkInfo enBuf;
+ // Check the type of file
+ fileType = _SystemSpecialFileBasedFilePath(filename, err, iFs);
+ // If it is a symbolic link, follow the link
+ // If _SystemSpecialFileBasedFilePath fails, treat it as normal file
+ // and try to proceed
+ if( fileType == EFileTypeSymLink && err == KErrNone )
+ {
+ err = _ReadSysSplFile(filename, (char*)&enBuf, sizeof(struct SLinkInfo), anErrno, iFs);
+ if (err == KErrNone)
+ {
+ filename = (wchar_t*)enBuf.iParentPath;
+ }
+ else
+ {
+ // errno is already set by _ReadSysSplFile
+ return -1;
+ }
+ }
+ else if ( fileType != EFileGeneralError && err != KErrNone )
+ {
+ return MapError(err,anErrno);
+ }
+ return PosixFilesystem::statbackend(iFs, filename, st, anErrno);
+ }
+
+int CLocalSystemInterface::lstat (const wchar_t* name, struct stat *st, int& anErrno)
+ {
+ return PosixFilesystem::statbackend(iFs, name, st, anErrno);
+ }
+
+int CLocalSystemInterface::utime (const wchar_t* name, const struct utimbuf *filetimes, int& anErrno)
+ {
+ return PosixFilesystem::utime(iFs, name, filetimes, anErrno);
+ }
+
+int CLocalSystemInterface::chmod (const wchar_t* name, int perms, int& anErrno)
+ {
+ return PosixFilesystem::chmod(iFs, name, perms, anErrno);
+ }
+
+int CLocalSystemInterface::rename (const wchar_t* oldname, const wchar_t* newname, int& anErrno)
+ {
+ return PosixFilesystem::rename(iFs, oldname, newname, anErrno);
+ }
+
+
+EXPORT_C TInt CLocalSystemInterface::ResolvePath (TParse& aResult, const wchar_t* path, TDes* aFilename)
+ {
+ return PosixFilesystem::ResolvePath(aResult, path, aFilename);
+ }
+
+// Simple layer over CFileTable synchronous routines
+
+int CLocalSystemInterface::open (const wchar_t* name, int mode, int perms, int& anErrno)
+ {
+ return iFids.open(name,mode,perms,anErrno);
+ }
+
+int CLocalSystemInterface::dup (int fid, int& anErrno)
+ {
+ return iFids.dup(fid,anErrno);
+ }
+
+int CLocalSystemInterface::dup2 (int fid, int fid2, int& anErrno)
+ {
+ return iFids.dup2(fid,fid2,anErrno);
+ }
+
+int CLocalSystemInterface::close (int fid, int& anErrno)
+ {
+ return iFids.UserClose(fid,anErrno);
+ }
+
+off_t CLocalSystemInterface::lseek (int fid, off_t offset, int whence, int& anErrno)
+ {
+ return iFids.lseek(fid,offset,whence,anErrno);
+ }
+
+int CLocalSystemInterface::fstat (int fid, struct stat *st, int& anErrno)
+ {
+ return iFids.fstat(fid,st,anErrno);
+ }
+
+int CLocalSystemInterface::socket (int family, int style, int protocol, int& anErrno)
+ {
+ //Acquire the Lock before issuing a request to the server and release it later
+ iSSLock.Wait();
+ int retVal = iFids.socket(family,style,protocol,anErrno,iSs);
+ iSSLock.Signal();
+ return retVal;
+ }
+
+int CLocalSystemInterface::listen (int fid, int n, int& anErrno)
+ {
+ return iFids.listen(fid,n,anErrno);
+ }
+
+int CLocalSystemInterface::bind (int fid, const struct sockaddr* addr, unsigned long size, int& anErrno)
+ {
+ return iFids.bind(fid,addr,size,anErrno);
+ }
+
+int CLocalSystemInterface::sockname (int fid, struct sockaddr* addr, unsigned long* size, int anEnd, int& anErrno)
+ {
+ return iFids.sockname(fid,addr,size,anEnd,anErrno);
+ }
+
+int CLocalSystemInterface::getsockopt (int fid, int level, int opt, void* buf, unsigned long* len, int& anErrno)
+ {
+ return iFids.getsockopt(fid,level,opt,buf,len,anErrno);
+ }
+
+int CLocalSystemInterface::setsockopt (int fid, int level, int opt, void* buf, unsigned long len, int& anErrno)
+ {
+ return iFids.setsockopt(fid,level,opt,buf,len,anErrno);
+ }
+
+int CLocalSystemInterface::popen3 (const wchar_t* file, const wchar_t* cmd,
+ wchar_t** env, int fids[3], int& anErrno)
+ {
+ return iFids.popen3(file, cmd, env, fids, anErrno);
+ }
+
+int CLocalSystemInterface::waitpid (int pid, int* status, int options, int& anErrno)
+ {
+ return iFids.waitpid(pid, status, options, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::popen
+// Implementation for popen
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::popen (const wchar_t* file, const wchar_t* cmd,
+ const char* mode, int& anErrno)
+ {
+ return iFids.popen(file, cmd, mode, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::pclose
+// Implementation for pclose
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::pclose (int aFid, int& anErrno)
+ {
+ return iFids.pclose(aFid, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::CheckOrigins
+// Implementation for CheckPipe
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLocalSystemInterface::CheckOrigins (wchar_t**& wenvp, int& aCount)
+ {
+ //Acquire the Lock before issuing a request to the server and release it later
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+ iFids.CheckOrigins(wenvp, aCount, iSigMask);
+#else
+ iFids.CheckOrigins(wenvp, aCount);
+#endif
+ }
+
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::WaitOrHandleSignal
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::WaitOrHandleSignal(TSignalMessage aMsg)
+ {
+ TInt lSigNum = 0,lIdx = 0,lSigVal = 0;
+ TSignalWaiter lTempWaiter(0,0);
+
+ if(aMsg.mType == TSignalMessage::ESignal)
+ lSigNum = aMsg.mSignal;
+ else if(aMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ lSigNum = aMsg.mSigVal.mSignal;
+ lSigVal = aMsg.mSigVal.mValue;
+ }
+ else if(aMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ lSigNum = aMsg.mRtSignal.mSignal;
+ }
+
+ // check and deliver to waiter (if any)
+ TUint64 lMask;
+ SIG_EMPTY_SIGSET(lMask);
+ SIG_ADD_SIGNAL_TO_SET(lSigNum,lMask);
+ lTempWaiter.iSigWaitMask = lMask;
+
+ lIdx = iSignalWaiterArray.Find(lTempWaiter,TSignalWaiter::MatchByMask);
+ if(lIdx != KErrNotFound)
+ {
+ iSignalWaiterMutex.Wait();
+ iSignalWaiterArray[lIdx].iSigWaitMessagePtr->mType = aMsg.mType;
+ if(aMsg.mType == TSignalMessage::ESignal)
+ iSignalWaiterArray[lIdx].iSigWaitMessagePtr->mSignal = lSigNum;
+ else if(aMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ iSignalWaiterArray[lIdx].iSigWaitMessagePtr->mSigVal.mSignal = lSigNum;
+ iSignalWaiterArray[lIdx].iSigWaitMessagePtr->mSigVal.mValue = lSigVal;
+ }
+ iSignalWaiterArray[lIdx].iSigWaitSemaphore.Signal();
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ iSignalWaiterArray.Remove(lIdx);
+ User::SwitchHeap(oldHeap);
+ iSignalWaiterMutex.Signal();
+ }
+ // queueing if blocked or sigqueue
+ else
+ {
+ HandleSignal(aMsg);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::SignalHandler
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::SignalHandler()
+ {
+ // TODO: Put memory barrier to ensure SMP safety
+ TInt lRetVal = KErrGeneral;
+ InitializeSignalHandlers();
+ RPipe::Init(); // check return value
+ lRetVal = RPipe::Create(KSignalPipeSize,iSignalReadPipe,iSignalWritePipe);
+ if(lRetVal != KErrNone)
+ {
+ iSignalInitSemaphore.Signal();
+ return lRetVal;
+ }
+ lRetVal = iSignalSession.SendPipe(iSignalWritePipe); // check return value
+ if(lRetVal != KErrNone)
+ {
+ iSignalInitSemaphore.Signal();
+ return lRetVal;
+ }
+
+ /* Closing the end of the pipe that's been sent to the server */
+ iSignalWritePipe.Close();
+
+ iSignalsInitialized = ETrue;
+ iSignalInitSemaphore.Signal();
+ iSignalLoopRunning = ETrue;
+ iPipeReadStatus = KRequestPending;
+ iSignalReadPipe.NotifyDataAvailable(iPipeReadStatus);
+ while(iSignalLoopRunning)
+ {
+ User::WaitForAnyRequest();
+ if(iSignalLoopRunning == false) {
+ break;
+ }
+ // Check if it is a pipe read
+ if(iPipeReadStatus != KRequestPending)
+ {
+ if(iPipeReadStatus == KErrNone)
+ {
+ TBuf8<KSigMsgLength> lMsgBuf;
+ TInt lRetVal = KErrNone;
+ lRetVal = iSignalReadPipe.Read(lMsgBuf,KSigMsgLength);
+ TSignalMessage lMsg;
+ TInt lIdx = 0;
+
+ if(lMsg.Unmarshall(lMsgBuf)==KErrNone && lRetVal >= 0)
+
+ {
+ TInt lIdx1 = 0, lIdx2 = 0, lIdx3 = 0;
+ TSignalMessage lTmpMsg1,lTmpMsg2,lTmpMsg3;
+ TBool lSignalsFound = ETrue;
+
+ TChildWaiter lWaiter;
+
+ switch(lMsg.mType)
+ {
+ case TSignalMessage::ESignalValuePair:
+ case TSignalMessage::ESignal:
+ case TSignalMessage::ERtTimerSignal:
+ WaitOrHandleSignal(lMsg);
+ break;
+ case TSignalMessage::EDequeueSignal:
+ lTmpMsg1.mType = TSignalMessage::ESignal;
+ lTmpMsg1.mSignal = lMsg.mSignal;
+
+ lTmpMsg2.mType = TSignalMessage::ESignalValuePair;
+ lTmpMsg2.mSigVal.mSignal = lMsg.mSignal;
+
+ lTmpMsg3.mType = TSignalMessage::ERtTimerSignal;
+ lTmpMsg3.mRtSignal.mSignal = lMsg.mSignal;
+ while(lSignalsFound)
+ {
+ iBlockedSAMutex.Wait();
+ lIdx1 = iBlockedSigArray.Find(lTmpMsg1,TSignalMessage::SignalMatchBySigNum);
+ lIdx2 = iBlockedSigArray.Find(lTmpMsg2,TSignalMessage::SigValMatchBySigNum);
+ lIdx3 = iBlockedSigArray.Find(lTmpMsg3,TSignalMessage::SigValMatchBySigNum);
+ iBlockedSAMutex.Signal();
+ if(lIdx1 == KErrNotFound && lIdx2 == KErrNotFound)
+ {
+ lSignalsFound = EFalse;
+ }
+ else
+ {
+ if(lIdx1 != KErrNotFound)
+ {
+ HandleSignal(lTmpMsg1,ETrue);
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Remove(lIdx1);
+ iBlockedSAMutex.Signal();
+ }
+ if(lIdx2 != KErrNotFound)
+ {
+ HandleSignal(lTmpMsg2,ETrue);
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Remove(lIdx2);
+ iBlockedSAMutex.Signal();
+ }
+ if(lIdx3 != KErrNotFound)
+ {
+ HandleSignal(lTmpMsg3, ETrue);
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Remove(lIdx3);
+ iBlockedSAMutex.Signal();
+ }
+ }
+ }
+ break;
+ case TSignalMessage::EAlarmRegistration:
+ if((iAlarmStatus == KRequestPending) && iIsTimerActive)
+ {
+ iAlarmTimer.Cancel();
+ iIsTimerActive = EFalse;
+ }
+ if(lMsg.mTimeOut)
+ {
+ iAlarmTimer.After(iAlarmStatus,lMsg.mTimeOut*1000000);
+ iAlarmStartTime.HomeTime();
+ iIsTimerActive = ETrue;
+ }
+ break;
+ case TSignalMessage::EWaitOnChild:
+ lWaiter.iWaiterPid = TProcessId(lMsg.mPid);
+ lWaiter.iWaiterStatus = KRequestPending;
+ lIdx = iChildWaiterArray.Find(lWaiter,TChildWaiter::MatchByPid);
+ if(lIdx == KErrNotFound)
+ {
+ lWaiter.iWaiterPid = TProcessId(lMsg.mPid);
+ lWaiter.iWaiterStatus = KRequestPending;
+ iChildWaiterArray.Append(lWaiter);
+ lIdx = iChildWaiterArray.Find(lWaiter,TChildWaiter::MatchByPid);
+ if(lIdx != KErrNotFound)
+ {
+ RProcess lProcess;
+ if(lProcess.Open(TProcessId(iChildWaiterArray[lIdx].iWaiterPid)) == KErrNone)
+ {
+ lProcess.Logon(iChildWaiterArray[lIdx].iWaiterStatus);
+ }
+ }
+ }
+ else
+ {
+ TProcessId lPid(iChildWaiterArray[lIdx].iWaiterPid);
+ iChildWaiterArray[lIdx].iWaiterStatus = KRequestPending;
+ RProcess lProcess(lPid);
+ lProcess.Logon(iChildWaiterArray[lIdx].iWaiterStatus);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ iPipeReadStatus = KRequestPending;
+ iSignalReadPipe.NotifyDataAvailable(iPipeReadStatus);
+ }
+ if((iAlarmStatus != KRequestPending) && iIsTimerActive)
+ {
+ if(iAlarmStatus == KErrNone)
+ {
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::ESignal;
+ lMsg.mSignal = SIGALRM;
+ WaitOrHandleSignal(lMsg);
+ }
+ iIsTimerActive = EFalse;
+ }
+ TBool lChildCheckRunning = ETrue;
+ while(lChildCheckRunning)
+ {
+ TChildWaiter lWaiter;
+ lWaiter.iWaiterStatus = KErrNone; // dummy waiter to match non pending waiters
+ TInt lTimerIdx = iChildWaiterArray.Find(lWaiter,TChildWaiter::MatchNotPending);
+ if(lTimerIdx != KErrNotFound)
+ {
+ TSignalMessage lSigChldMsg;
+ lSigChldMsg.mType = TSignalMessage::ESignal;
+ lSigChldMsg.mSignal = SIGCHLD;
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lSigChldMsg.Marshall(lMsgBuf);
+ iSignalWritePipe.Write(lMsgBuf,KSigMsgLength);
+ iChildWaiterArray.Remove(lTimerIdx);
+ }
+ else
+ {
+ lChildCheckRunning = EFalse;
+ }
+ }
+ }
+ if(iPipeReadStatus == KRequestPending)
+ {
+ iSignalReadPipe.CancelDataAvailable();
+ }
+ iSignalReadPipe.Close();
+
+ if(iAlarmStatus == KRequestPending)
+ {
+ iAlarmTimer.Cancel();
+ }
+ TInt lCounterIdx = 0;
+ for(lCounterIdx = 0; lCounterIdx < iChildWaiterArray.Count(); lCounterIdx++)
+ {
+ if(iChildWaiterArray[lCounterIdx].iWaiterStatus == KRequestPending)
+ {
+ RProcess lProcess;
+ if(lProcess.Open(TProcessId(iChildWaiterArray[lCounterIdx].iWaiterPid)) == KErrNone)
+ {
+ lProcess.LogonCancel(iChildWaiterArray[lCounterIdx].iWaiterStatus);
+ lProcess.Close();
+ }
+ }
+ }
+ iSignalSession.Close();
+ return KErrNone;
+ }
+
+static TInt sSignalHandler(TAny* aData)
+ {
+ CLocalSystemInterface* lClsi = 0;
+ TInt ret = 0;
+ if(aData == 0)
+ return KErrGeneral;
+
+ lClsi = static_cast<CLocalSystemInterface*>(aData);
+ CTrapCleanup* pCleanup = CTrapCleanup::New();
+ if (pCleanup)
+ {
+ ret = lClsi->SignalHandler();
+ delete pCleanup;
+ }
+ else
+ {
+ ret = KErrNoMemory;
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::InitSignalHandler
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLocalSystemInterface::InitSignalHandler()
+ {
+ if(iSignalsInitialized)
+ return;
+
+ // Create thread
+ iSignalHandlerThread.Create(KNullDesC,sSignalHandler,KDefaultStackSize,NULL,this);
+ // Raise priority
+ iSignalHandlerThread.SetPriority(EPriorityAbsoluteHigh);
+ iSignalHandlerThread.Resume();
+
+ iSignalInitSemaphore.Wait();
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::EnsureSignalsInitialized
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::EnsureSignalsInitialized()
+ {
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::SigWaitInternal
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::SigWaitInternal(TUint64 aWaitSet,TSignalMessage* aMsg,TInt aTimeout,TBool aTimeCheckFailed)
+ {
+ if(aWaitSet == 0)
+ return KErrArgument;
+
+ TInt lArrayIdx = 0,lSignalIdx = 1;
+ while(lSignalIdx <= SIGRTMAX)
+ {
+ if(SIG_SIGNAL_PRESENT_IN_SIGSET(lSignalIdx,aWaitSet) && lSignalIdx != SIGKILL && lSignalIdx != SIGSTOP)
+ {
+ TSignalMessage lTmpMsg;
+
+ lTmpMsg.mType = TSignalMessage::ESignal;
+ lTmpMsg.mSignal = lSignalIdx;
+ iBlockedSAMutex.Wait();
+ lArrayIdx = iBlockedSigArray.Find(lTmpMsg,TSignalMessage::SignalMatchBySigNum);
+ iBlockedSAMutex.Signal();
+ if(lArrayIdx != KErrNotFound)
+ {
+ if(aMsg)
+ {
+ aMsg->mType = TSignalMessage::ESignal;
+ iBlockedSAMutex.Wait();
+ aMsg->mSignal = iBlockedSigArray[lArrayIdx].mSignal;
+ iBlockedSAMutex.Signal();
+ }
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Remove(lArrayIdx);
+ iBlockedSAMutex.Signal();
+ return KErrNone;
+ }
+
+ lTmpMsg.mType = TSignalMessage::ESignalValuePair;
+ lTmpMsg.mSigVal.mSignal = lSignalIdx;
+ iBlockedSAMutex.Wait();
+ lArrayIdx = iBlockedSigArray.Find(lTmpMsg,TSignalMessage::SigValMatchBySigNum);
+ iBlockedSAMutex.Signal();
+ if(lArrayIdx != KErrNotFound)
+ {
+ if(aMsg)
+ {
+ aMsg->mType = TSignalMessage::ESignalValuePair;
+ iBlockedSAMutex.Wait();
+ aMsg->mSigVal.mSignal = iBlockedSigArray[lArrayIdx].mSigVal.mSignal;
+ aMsg->mSigVal.mValue = iBlockedSigArray[lArrayIdx].mSigVal.mValue;
+ iBlockedSAMutex.Signal();
+ }
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Remove(lArrayIdx);
+ iBlockedSAMutex.Signal();
+ return KErrNone;
+ }
+
+ lTmpMsg.mType = TSignalMessage::ERtTimerSignal;
+ lTmpMsg.mRtSignal.mSignal = lSignalIdx;
+ iBlockedSAMutex.Wait();
+ lArrayIdx = iBlockedSigArray.Find(lTmpMsg,TSignalMessage::SigValMatchBySigNum);
+ iBlockedSAMutex.Signal();
+ if(lArrayIdx != KErrNotFound)
+ {
+ if(aMsg)
+ {
+ aMsg->mType = TSignalMessage::ERtTimerSignal;
+ iBlockedSAMutex.Wait();
+ aMsg->mRtSignal.mSignal = iBlockedSigArray[lArrayIdx].mRtSignal.mSignal;
+ iBlockedSAMutex.Signal();
+ }
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Remove(lArrayIdx);
+ iBlockedSAMutex.Signal();
+ return KErrNone;
+ }
+ }
+ lSignalIdx++;
+ }
+
+ if(aTimeCheckFailed)
+ return KErrGeneral;
+
+ TSignalMessage lMsg;
+ TSignalWaiter lWaiter(aWaitSet,&lMsg);
+
+ iSignalWaiterMutex.Wait();
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ iSignalWaiterArray.Append(lWaiter);
+ User::SwitchHeap(oldHeap);
+
+ iSignalWaiterMutex.Signal();
+ if(aTimeout > 0)
+ {
+ TInt lRetVal = lWaiter.iSigWaitSemaphore.Wait(aTimeout);
+ if(lRetVal != KErrNone)
+ {
+ // Timed out
+ TSignalWaiter lTempWaiter(0,0);
+ TInt lIdx;
+ iSignalWaiterMutex.Wait();
+ lIdx = iSignalWaiterArray.Find(lTempWaiter,TSignalWaiter::MatchByThreadId);
+ if(lIdx != KErrNotFound)
+ {
+ oldHeap = User::SwitchHeap(iPrivateHeap);
+ iSignalWaiterArray.Remove(lIdx);
+ User::SwitchHeap(oldHeap);
+ }
+ iSignalWaiterMutex.Signal();
+ return KErrTimedOut;
+ }
+ }
+ else
+ lWaiter.iSigWaitSemaphore.Wait();
+
+ TSignalWaiter lTempWaiter(0,0);
+ TInt lIdx = 0;
+ iSignalWaiterMutex.Wait();
+ lIdx = iSignalWaiterArray.Find(lTempWaiter,TSignalWaiter::MatchByThreadId);
+ if(lIdx != KErrNotFound)
+ {
+ oldHeap = User::SwitchHeap(iPrivateHeap);
+ iSignalWaiterArray.Remove(lIdx);
+ User::SwitchHeap(oldHeap);
+ }
+ iSignalWaiterMutex.Signal();
+
+ if(lMsg.mType == TSignalMessage::ESignal)
+ {
+ aMsg->mType = TSignalMessage::ESignal;
+ aMsg->mSignal = lMsg.mSignal;
+ }
+ else if(lMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ aMsg->mType = TSignalMessage::ESignalValuePair;
+ aMsg->mSigVal.mSignal = lMsg.mSigVal.mSignal;
+ aMsg->mSigVal.mValue = lMsg.mSigVal.mValue;
+ }
+ else if(lMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ aMsg->mType = TSignalMessage::ERtTimerSignal;
+ aMsg->mRtSignal.mSignal = lMsg.mRtSignal.mSignal;
+ }
+ else
+ {
+ return KErrGeneral;
+ }
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::RegisterExitNotification
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::RegisterExitNotification(TProcessId aPid)
+ {
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::EWaitOnChild;
+ lMsg.mPid = aPid.Id();
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lMsg.Marshall(lMsgBuf);
+ iSignalWritePipe.Write(lMsgBuf,KSigMsgLength);
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::InitializeSigHandlers
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::InitializeSignalHandlers()
+ {
+ iSigHandlerMutex.CreateLocal();
+ iAlarmTimer.CreateLocal(); // what should be done if fails
+ iIsTimerActive = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::HandleSignal
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::HandleSignal(TSignalMessage& aMsg,TBool aIsDequeued)
+ {
+ TUint8 lSigNum = 0;
+
+ if(aMsg.mType == TSignalMessage::ESignal)
+ lSigNum = aMsg.mSignal;
+ else if(aMsg.mType == TSignalMessage::ERtTimerSignal)
+ lSigNum = aMsg.mRtSignal.mSignal;
+ else
+ lSigNum = aMsg.mSigVal.mSignal;
+
+ if(lSigNum <= 0 || lSigNum > SIGRTMAX)
+ return;
+
+ if(SIG_SIGNAL_PRESENT_IN_SIGSET(lSigNum,iSigMask) && !aIsDequeued)
+ {
+ TInt lIdx = 0;
+ TSignalMessage lTmpMsg;
+
+ lTmpMsg.mType = aMsg.mType;
+ if(aMsg.mType == TSignalMessage::ESignal)
+ {
+ lTmpMsg.mSignal = aMsg.mSignal;
+ iBlockedSAMutex.Wait();
+ lIdx = iBlockedSigArray.Find(lTmpMsg,TSignalMessage::SignalMatchBySigNum);
+ iBlockedSAMutex.Signal();
+ if(lIdx == KErrNotFound || lSigNum >= SIGRTMIN)
+ {
+ lTmpMsg.mType = TSignalMessage::ESignal;
+ lTmpMsg.mSignal = aMsg.mSignal;
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Append(lTmpMsg);
+ iBlockedSAMutex.Signal();
+ }
+ }
+ else if(aMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ lTmpMsg.mSigVal.mSignal = aMsg.mSigVal.mSignal;
+ lTmpMsg.mSigVal.mValue = aMsg.mSigVal.mValue;
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Append(lTmpMsg);
+ iBlockedSAMutex.Signal();
+ }
+ else if(aMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ lTmpMsg.mSignal = aMsg.mRtSignal.mSignal;
+ iBlockedSAMutex.Wait();
+ lIdx = iBlockedSigArray.Find(lTmpMsg,TSignalMessage::SignalMatchBySigNum);
+ iBlockedSAMutex.Signal();
+ if(lIdx == KErrNotFound || lSigNum >= SIGRTMIN)
+ {
+ lTmpMsg.mType = TSignalMessage::ERtTimerSignal;
+ lTmpMsg.mRtSignal.mSignal = aMsg.mRtSignal.mSignal;
+ iBlockedSAMutex.Wait();
+ iBlockedSigArray.Append(lTmpMsg);
+ iBlockedSAMutex.Signal();
+ }
+ }
+
+ return;
+ }
+ else
+ {
+ SuspendOtherThreads();// suspend all other threads
+ TUint32 lSigVal = 0;
+ TSignalHandler lCurHandler = 0;
+ TSignalAction lCurAction = 0;
+
+ if(aMsg.mType == TSignalMessage::ESignal)
+ lSigNum = aMsg.mSignal;
+ else if(aMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ lSigNum = aMsg.mSigVal.mSignal;
+ lSigVal = aMsg.mSigVal.mValue;
+ }
+ else if(aMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ lSigNum = aMsg.mRtSignal.mSignal;
+#ifdef SYMBIAN_OE_LIBRT
+ //reset the overrun count before calling the handler/action.
+ ResetOverrun(aMsg.mRtSignal.mTimerId);
+#endif //SYMBIAN_OE_LIBRT
+ }
+ else
+ {
+ ResumeOtherThreads();
+ return;
+ }
+ iSigHandlerMutex.Wait();
+ lCurHandler = iSigActions[lSigNum -1].iSigHandler;
+ lCurAction = iSigActions[lSigNum-1].iSigAction;
+
+ if(lCurAction)
+ {
+ siginfo_t lsiginfo;
+ lsiginfo.si_signo = lSigNum;
+ lsiginfo.si_value.sival_int = lSigVal;
+ lCurAction(lSigNum,&lsiginfo,(void*)0); // setting context as 0
+ }
+ else
+ {
+ if(lCurHandler == SIG_DFL)
+ {
+ CallDefaultHandler(lSigNum);
+ }
+ else if(lCurHandler != SIG_IGN)
+ {
+ lCurHandler(lSigNum);
+ }
+ }
+ ResumeOtherThreads();// resume all other threads
+ }
+
+ if(iSigActions[lSigNum -1].iSigFlags & SA_RESETHAND)
+ {
+ iSigActions[lSigNum -1].iSigHandler = SIG_DFL;
+ }
+ iSigHandlerMutex.Signal();
+
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// sig_exit
+// -----------------------------------------------------------------------------
+//
+static void sig_exit()
+ {
+ Backend()->Exit(0); // Check if clean exit or terminate is to be done
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::CallDefaultHandler
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::CallDefaultHandler(int aSigNum)
+ {
+ if(aSigNum < 1 || aSigNum > SIGRTMAX)
+ return;
+
+ switch(aSigNum)
+ {
+ case SIGTERM:
+ case SIGKILL:
+ case SIGALRM:
+ case SIGPIPE:
+ sig_exit();
+ break;
+ case SIGQUIT:
+ default:
+ // SIG_IGN - Do nothing;
+ break;
+ }
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::SuspendOtherThreads
+// -----------------------------------------------------------------------------
+//
+_LIT(KThreadFormatString,"*");
+
+TInt CLocalSystemInterface::SuspendOtherThreads()
+ {
+ TFileName lProcessName = RProcess().FileName();
+ TBuf<256> lThreadNameString;
+ TFullName lThreadName;
+
+#ifdef SYMBIAN_OE_LIBRT
+ TBool lFoundTimerServ = EFalse;
+#endif
+
+ TParsePtr lParser(lProcessName);
+ TPtrC lName = lParser.NameAndExt();
+
+
+ lThreadNameString.Append(lName);
+ lThreadNameString.Append(KThreadFormatString);
+
+ TFindThread lFindPattern(lThreadNameString);
+ TInt lRetVal = KErrNone;
+
+ while(lRetVal == KErrNone)
+ {
+ lRetVal = lFindPattern.Next(lThreadName);
+ if(lRetVal == KErrNone)
+ {
+#ifdef SYMBIAN_OE_LIBRT
+ if(!lFoundTimerServ && (lThreadName.Match(_L("*LibrtTimerServ")) != KErrNotFound))
+ {
+ lFoundTimerServ = ETrue;
+ continue;
+ }
+#endif
+ RThread lThread;
+ RProcess lProcess;
+ if(lThread.Open(lThreadName) == KErrNone)
+ {
+ lThread.Process(lProcess);
+ if( (lProcess.Id() == RProcess().Id()) &&
+ (lThread.Id() != RThread().Id()) )
+ lThread.Suspend();
+ lThread.Close();
+ }
+ }
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::ResumeOtherThreads
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::ResumeOtherThreads()
+ {
+ TFileName lProcessName = RProcess().FileName();
+ TBuf<256> lThreadNameString;
+ TFullName lThreadName;
+#ifdef SYMBIAN_OE_LIBRT
+ TBool lFoundTimerServ = EFalse;
+#endif
+ TParsePtr lParser(lProcessName);
+ TPtrC lName = lParser.NameAndExt();
+
+
+ lThreadNameString.Append(lName);
+ lThreadNameString.Append(KThreadFormatString);
+
+ TFindThread lFindPattern(lThreadNameString);
+ TInt lRetVal = KErrNone;
+
+ while(lRetVal == KErrNone)
+ {
+ lRetVal = lFindPattern.Next(lThreadName);
+ if(lRetVal == KErrNone)
+ {
+#ifdef SYMBIAN_OE_LIBRT
+ if(!lFoundTimerServ && (lThreadName.Match(_L("*LibrtTimerServ")) != KErrNotFound))
+ {
+ lFoundTimerServ = ETrue;
+ continue;
+ }
+#endif
+ RThread lThread;
+ RProcess lProcess;
+ if(lThread.Open(lThreadName) == KErrNone)
+ {
+ lThread.Process(lProcess);
+ if( (lProcess.Id() == RProcess().Id()) &&
+ (lThread.Id() != RThread().Id()) )
+ lThread.Resume();
+ lThread.Close();
+ }
+ }
+ }
+
+ return KErrNone;
+ }
+
+#endif // SYMBIAN_OE_POSIX_SIGNALS
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::fcntl
+// Implementation for fcntl
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::fcntl (int aFid, int aCmd, long anArg, int& anErrno)
+ {
+ return iFids.fcntl(aFid, aCmd, anArg, anErrno);
+ }
+
+
+int CLocalSystemInterface::fchmod (int fd , mode_t perms, int& anErrno)
+ {
+ CFileDescBase *f = NULL;
+
+ TInt err = iFids.At(fd, f);
+
+ if(!err)
+ {
+ switch(perms & (S_IWUSR | S_IRUSR ))
+ {
+ case S_IRUSR | S_IWUSR :
+ case S_IWUSR :
+ {
+ err = f->SetAtt(0, KEntryAttReadOnly);
+ break;
+ }
+ case S_IRUSR :
+ {
+ err = f->SetAtt(KEntryAttReadOnly, 0);
+ break;
+ }
+ default :
+ {
+ err = KErrArgument;
+ break;
+ }
+ }
+ }
+ return MapError(err, anErrno);
+ }
+
+// Synchronous layer over CFileTable asynchronous routines
+int CLocalSystemInterface::read (int fid, char* buf, unsigned long len, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TBool patchErr = EFalse;
+
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ //if the file is WRONLY then return Error here
+ TUint flgs = f->Fcntl(fid, F_GETFL);
+ if ((flgs & O_ACCMODE) == O_WRONLY)
+ {
+ anErrno = EBADF;
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ return -1;
+ }
+
+ TRequestStatus readStatus;
+ TRequestStatus timerStatus(KRequestPending);
+ RTimer theTimer;
+ TBool timerRunning = EFalse;
+
+ TPtr8 ptr((TText8 *)buf, len);
+
+ if (f->TimedRead())
+ {
+ TTimeIntervalMicroSeconds32 timeout(f->TimeoutValue()*1000);
+ theTimer.CreateLocal();
+ theTimer.After(timerStatus, timeout);
+ timerRunning = ETrue;
+ }
+
+ //If its console based, fid = {0, 1, 2 }
+ if( fid >= 0 && fid <= 2 )
+ {
+ f->SetFid(fid);
+ }
+
+ f->Read(ptr, readStatus);
+
+ User::WaitForRequest(readStatus, timerStatus);
+
+ if (timerRunning)
+ {
+ if (timerStatus.Int() != KRequestPending)
+ {
+ //cancel the read and wait for it
+ f->ReadCancel();
+ patchErr = ETrue; //report this as a timeout not a cancel!!
+ User::WaitForRequest(readStatus);
+ }
+ else
+ {
+ //if the timer was in operation
+ //cancel the timer
+ theTimer.Cancel();
+ User::WaitForRequest(timerStatus);
+ }
+ theTimer.Close();
+ }
+
+ err=f->ReadCompletion(ptr, readStatus.Int());
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ if (err>0)
+ return err;
+ else if( (f->Attributes() & KPipeFd )|| (fid == 0))
+ {
+ // if EOF is reached in case of pipes or stdin
+ // TODO: Verify that this check is valid for console or comm-based stdin?
+ if(err == KErrEof)
+ {
+ MapError(err,anErrno);
+ return 0;
+ }
+ }
+ else if( f->Type()==CFileDescBase::ESocketDesc || f->Type()==CFileDescBase::EFileSocketDesc)
+ {
+ // if EOF is reached for the Socket return 0
+ if(err == KErrEof)
+ {
+ return 0;
+ }
+ if(err == KErrDisconnected)
+ {
+ err = ECONNRESET;
+ }
+ }
+ }
+ if (patchErr)
+ err = ETIMEDOUT;
+
+ return MapError(err,anErrno);
+ }
+
+int CLocalSystemInterface::write (int fid, const char* buf, unsigned long len, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ TRequestStatus status;
+ TPtr8 ptr((TText8 *)buf, len, len);
+
+ //If its console based, fid = {0, 1, 2 }
+ if( fid >= 0 && fid <= 2 )
+ {
+ f->SetFid(fid);
+ }
+
+ TUint flgs = f->Fcntl(fid, F_GETFL);
+
+ if((flgs & O_ACCMODE) == O_RDONLY)
+ {
+ anErrno = EBADF;
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ return -1;
+ }
+ f->Write(ptr,status);
+ User::WaitForRequest(status);
+ err=f->WriteCompletion(ptr, status.Int());
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ if (err > 0)
+ return err;
+ if((f->Type() == CFileDescBase::EFileSocketDesc || f->Type() == CFileDescBase::ESocketDesc) && err == KErrDisconnected)
+ {
+ err = ECONNRESET;
+ }
+ }
+ return MapError(err,anErrno);
+ }
+
+int CLocalSystemInterface::recvfrom (int fid, char* buf, unsigned long len, int flags, struct sockaddr* from, unsigned long* fromsize, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ TRequestStatus status;
+ TPtr8 ptr((TText8 *)buf, len);
+ struct sockaddr tmpAddr;
+ TUSockAddr addr(&tmpAddr);
+ f->RecvFrom(ptr,addr,flags,status);
+ User::WaitForRequest(status);
+ TInt ret=0;
+ err=f->CompletionStatus(ret, status.Int());
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ if (err==0)
+ {
+ if(f->Type() == CFileSocketDesc::EFileSocketDesc)
+ {
+ ((CFileSocketDesc*)f)->GetLocalSockAddrByPort((sockaddr_un*)from,fromsize,addr.Port());
+ }
+ else
+ {
+ addr.Get(from,fromsize);
+ }
+
+ return ptr.Length();
+ }
+ }
+ if(err == KErrDisconnected)
+ {
+ anErrno = ECONNRESET;
+ return -1;
+ }
+ if (err == KErrWouldBlock)
+ {
+ return MapError(EAGAIN, anErrno);
+ }
+ else
+ {
+ return MapError(err,anErrno);
+ }
+ }
+
+int CLocalSystemInterface::sendto (int fid, const char* buf, unsigned long len, int flags, struct sockaddr* to, unsigned long tosize, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ TRequestStatus status;
+ TPtr8 ptr((TText8 *)buf, len, len);
+ TInt bytesSent = 0;
+ f->SendTo(ptr,to,tosize,flags,status);
+ User::WaitForRequest(status);
+ err=f->CompletionStatus(bytesSent, status.Int());
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ if (err==0)
+ {
+ return bytesSent;
+ }
+ }
+ if (err == KErrNotReady)
+ {
+ anErrno = EPIPE;
+ return -1;
+ }
+ if(err == KErrDisconnected)
+ {
+ anErrno = ECONNRESET;
+ return -1;
+ }
+
+ // A Hack to convert KErrTooBig to EMSGSIZE for this API.
+ // For any KErrTooBig, MapError will convert it to EFAULT.
+ if (err == KErrTooBig)
+ {
+ anErrno = EAGAIN;
+ return -1;
+ }
+ return MapError(err,anErrno);
+ }
+
+int CLocalSystemInterface::fsync (int fid, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ TRequestStatus status;
+ f->Sync(status);
+ User::WaitForRequest(status);
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ err=status.Int();
+ }
+ return MapError(err,anErrno);
+ }
+
+int CLocalSystemInterface::shutdown (int fid, int how, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ TRequestStatus status;
+ f->Shutdown(how,status);
+ User::WaitForRequest(status);
+ err=status.Int();
+ // SOS does not allow to RSocket::Shutdown() immediately.
+ if (err == KErrNotSupported)
+ {
+ err = 0;
+ }
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ }
+ return MapError(err,anErrno);
+ }
+
+int CLocalSystemInterface::connect (int fid, const struct sockaddr* addr, unsigned long size, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ TInt mapErr = err;
+
+ if(!err)
+ {
+ // Check if a connection request is already in progress
+ // for a non-blocking socket.
+ if(f->GetConnectionProgress())
+ {
+ // Poll to see if the connect() is completed
+ err = f->Poll( EReadyForWriting );
+
+ // The above Poll is common for all descriptors.
+ // In case of socket-descriptors, Poll will either return "KErrNone"
+ // or any of the requested events. To check for Poll error in case of
+ // socket-descriptors, "iPollErr" should be checked.
+ if( (err < 0) || (f->iPollErr < 0) ) //Error in poll
+ (err < 0) ? (mapErr = err):(mapErr = f->iPollErr);
+ else if( err == 0 ) //Connect still in progress
+ mapErr = EALREADY;
+ else if( err & EReadyForWriting ) //Connect has completed
+ f->SetConnectionProgress(EFalse);
+ }
+
+ if(!mapErr)
+ {
+ TRequestStatus status;
+ f->Connect(addr,size,status);
+ err=status.Int();
+
+ if (err == KErrWouldBlock)
+ {
+ f->SetConnectionProgress(ETrue);
+ mapErr = EINPROGRESS;
+ }
+ else if(err == KErrAlreadyExists)
+ {
+ mapErr = EISCONN;
+ }
+ else
+ mapErr = err;
+ }
+
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ }
+
+ return MapError(mapErr, anErrno);
+
+ }
+
+//
+// The CSocketDesc performing the Accept is responsible for creating the new CSocketDesc
+//
+int CLocalSystemInterface::accept (int fid, struct sockaddr *addr, size_t *size, int& anErrno)
+ {
+
+ size_t addrlen = 0;
+ if (addr && !size)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+ else if (size)
+ {
+ addrlen = *size;
+ }
+
+ TUSockAddr address((TAny*)addr, addrlen);
+ /* Accept implementations that use the TUSockAddr* param, first need to assert address.iError == 0 */
+
+ CFileDescBase* f = 0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ CFileDescBase* newf=0;
+ int fd=iFids.Reserve();
+ if (fd>=0)
+ {
+ TRequestStatus status;
+ //Acquire the Lock before issuing a request to the server and release it later
+ iSSLock.Wait();
+
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ //coverity[alloc_fn]
+ f->Accept(newf,status,iSs, &address);
+ User::SwitchHeap(oldHeap);
+
+ iSSLock.Signal();
+ User::WaitForRequest(status);
+ //coverity[leave_without_push]
+ f->Close(); // balances the Dup() in CFileTable::Asynch()
+ err=status.Int();
+ if (!err)
+ {
+ err=iFids.Attach(fd,newf);
+ if (!err)
+ return fd;
+ newf->Close();
+ }
+ else if(newf != NULL)
+ {
+ //coverity[leave_without_push]
+ newf->Close();
+ }
+ iFids.Attach(fd,0); // cancel the reservation
+ }
+ //coverity[memory_leak]
+ }
+ if (err == KErrNotReady)
+ {
+ return MapError(EINVAL,anErrno);
+ }
+ else if (err == KErrWouldBlock)
+ {
+ return MapError(EWOULDBLOCK, anErrno);
+ }
+ else
+ {
+ return MapError(err,anErrno);
+ }
+ }
+
+int CLocalSystemInterface::ioctl (int fid, int cmd, void* param, int& anErrno)
+ {
+ TRequestStatus ioctlStatus;
+ TInt err=ioctl(fid,cmd,param,ioctlStatus,anErrno);
+ if (err==KErrNone)
+ {
+ User::WaitForRequest(ioctlStatus);
+ err=ioctl_complete(fid,cmd,param,ioctlStatus,anErrno);
+ }
+ return err;
+ }
+
+// C++ version of asynchronous ioctl
+
+int CLocalSystemInterface::ioctl (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno)
+ {
+ CFileDescBase* f=0;
+ TInt err=iFids.Asynch(fid,f);
+ if (!err)
+ {
+ f->Ioctl(cmd,param,aStatus);
+ f->Close(); // balances the Dup() in CFileTable::Asynch() - live dangerously!
+ }
+ return MapError(err,anErrno);
+ }
+
+int CLocalSystemInterface::ioctl_complete (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno)
+ {
+ return iFids.ioctlcomplete(fid,cmd,param,aStatus,anErrno);
+ }
+
+#ifdef __SYMBIAN_COMPILE_UNUSED__
+int CLocalSystemInterface::ioctl_cancel (int fid, int& anErrno)
+ {
+ return iFids.ioctlcancel(fid,anErrno);
+ }
+#endif //__SYMBIAN_COMPILE_UNUSED__
+
+
+int CLocalSystemInterface::pipe(int fildes[2], int& anErrno )
+ {
+ return iFids.pipe(fildes, anErrno);
+ }
+
+int CLocalSystemInterface::mkfifo(const wchar_t *pathName, mode_t mode, int& anErrno )
+ {
+ return iFids.mkfifo(pathName, mode, anErrno, iFs);
+ }
+
+int CLocalSystemInterface::link(const wchar_t *oldpathName, const wchar_t *newpathName, int& anErrno )
+ {
+ return iFids.link(oldpathName, newpathName, anErrno, iFs);
+ }
+
+int CLocalSystemInterface::unlink(const wchar_t *pathName, int& anErrno )
+ {
+ return iFids.unlink(iFs, pathName, anErrno);
+ }
+
+int CLocalSystemInterface::select(int maxfd, fd_set* readfds,fd_set* writefds,
+ fd_set* exceptfds, struct timeval* tvptr, int& anErrno)
+ {
+ // select is nothing but eselect without any TRequestStatus array
+ return eselect(maxfd,readfds,writefds,exceptfds,tvptr,0,NULL,anErrno);
+ }
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::aselect
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::aselect(int maxfd, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *tvptr, TRequestStatus* requeststatus,
+ int& anErrno)
+ {
+ // Create a seperate thread to handle the aselect
+ return CreateaselectThread(maxfd, readfds, writefds, exceptfds, tvptr,
+ requeststatus,anErrno);
+ }
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::aselect
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::cancelaselect(TRequestStatus* requeststatus,int& anErrno,int performcleanup)
+ {
+ iASelectLock.Wait();
+ // Search for the aselect request entry in the aselect request array
+ for ( TInt i=0; i<iASelectRequest.Count(); i++ )
+ {
+ if( (iASelectRequest[i].iRequestStatus == requeststatus) || performcleanup )
+ {
+ // The specified request exists
+ RThread threadHandle;
+ // Open a handle to the service thread
+ TInt res = threadHandle.Open(iASelectRequest[i].iThreadId,EOwnerThread);
+ if( res == KErrNone )
+ {
+ // Kill the service thread
+ threadHandle.Kill(KErrCancel);
+ threadHandle.Close();
+ if( !performcleanup )
+ {
+ // Complete the request with KErrcancel
+ User::RequestComplete(iASelectRequest[i].iRequestStatus,KErrCancel);
+ }
+ // Switch to backend heap
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ // Remove the request details from the array
+ iASelectRequest.Remove(i);
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ if( !performcleanup )
+ {
+ iASelectLock.Signal();
+ return MapError(KErrNone, anErrno);
+ }
+ }
+ else
+ {
+ if( !performcleanup )
+ {
+ iASelectLock.Signal();
+ // unable to open a handle to the service thread
+ return MapError(res, anErrno);
+ }
+ }
+ }
+ }
+ iASelectLock.Signal();
+ // No request found with the specified TRequestStatus object
+ if( !performcleanup )
+ {
+ return MapError(KErrNotFound, anErrno);
+ }
+ else
+ {
+ return MapError(KErrNone, anErrno);
+ }
+ }
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::ASelectRequest
+// -----------------------------------------------------------------------------
+//
+RArray<TASelectRequest>& CLocalSystemInterface::ASelectRequest()
+ {
+ // Return a reference to the array
+ return iASelectRequest;
+ }
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::ASelectLock
+// -----------------------------------------------------------------------------
+//
+RFastLock& CLocalSystemInterface::ASelectLock()
+ {
+ // Return a reference to the array
+ return iASelectLock;
+ }
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::eselect
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::eselect(int maxfd, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *tvptr, int arraycount,
+ TRequestStatus* waitarray,int& anErrno)
+ {
+ unsigned long timeout = 0;
+ if (tvptr)
+ {
+ if (tvptr->tv_sec < 0 || tvptr->tv_usec < 0)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+ // converting to micro seconds
+ timeout = KConvertToMicroSecond * tvptr->tv_sec + tvptr->tv_usec;
+ }
+
+ // validate maxfd
+ if (maxfd < 0 || maxfd > FD_SETSIZE)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+ // maxfd should not be more than OPEN_MAX
+ if(maxfd > OPEN_MAX)
+ {
+ maxfd = OPEN_MAX;
+ }
+
+ if (!readfds && !writefds && !exceptfds && ((arraycount == 0) || (waitarray == NULL)) )
+ {
+ if (tvptr)
+ {
+ // select is being used as a better resolution timer
+ User::After(timeout);
+ anErrno = ETIMEDOUT;
+ return 0;
+ }
+ // hang forever? - according to spec, until interuppted by signal
+ TRequestStatus req = KRequestPending;
+ User::WaitForRequest(req);
+ }
+
+ fd_set retreadfds;
+ fd_set retwritefds;
+ fd_set retexceptfds;
+ FD_ZERO(&retreadfds);
+ FD_ZERO(&retwritefds);
+ FD_ZERO(&retexceptfds);
+
+ // Intially perform synchronous non-blocking polls to see if any of the
+ // input file descriptors are ready for read/write/error conditions.
+ // In the meantime also determine, how many TRequestStatus objects we will
+ // need for the next async run.
+ CFileDescBase* fdesc = NULL;
+ TInt nDescriptorsSet = 0;
+ TInt numReqs = 0;
+ TInt err = 0;
+
+ for (int i = 0; i < maxfd; ++i)
+ {
+ TUint events = 0;
+ if (readfds && FD_ISSET(i, readfds))
+ {
+ events = EReadyForReading;
+ }
+ if (writefds && FD_ISSET(i, writefds))
+ {
+ events |= EReadyForWriting;
+ }
+ if (exceptfds && FD_ISSET(i, exceptfds))
+ {
+ events |= EAnyException;
+ }
+ if (!events)
+ {
+ continue;
+ }
+ if (iFids.At(i, fdesc) != KErrNone)
+ {
+ // Bad input file descriptor
+ anErrno = EBADF;
+ return -1;
+ }
+ // Poll on this descriptor
+ err = fdesc->Poll(events);
+ if (err < 0)
+ {
+ if(err == KErrNotSupported)
+ {
+ // continue if a write event is being set on the read end of pipe or vice-versa
+ continue;
+ }
+ // An error - we should return
+ return MapError(err, anErrno);
+ }
+ else
+ {
+ if (err & EReadyForReading)
+ {
+ FD_SET(i, &retreadfds);
+ ++nDescriptorsSet;
+ }
+ if (err & EReadyForWriting)
+ {
+ FD_SET(i, &retwritefds);
+ ++nDescriptorsSet;
+ }
+ if (err & EAnyException)
+ {
+ FD_SET(i, &retexceptfds);
+ ++nDescriptorsSet;
+ }
+ ++numReqs;
+ }
+ }
+
+ if (nDescriptorsSet || (tvptr && timeout == 0))
+ {
+ // Some of the descriptors are ready for requested operations. Return.
+ if (readfds)
+ {
+ FD_COPY(&retreadfds, readfds);
+ }
+ if (writefds)
+ {
+ FD_COPY(&retwritefds, writefds);
+ }
+ if (exceptfds)
+ {
+ FD_COPY(&retexceptfds, exceptfds);
+ }
+ return nDescriptorsSet;
+ }
+
+ if (numReqs == 0 && ((arraycount == 0) || (waitarray == NULL)) )
+ {
+ if (tvptr)
+ {
+ User::After(timeout);
+ anErrno = ETIMEDOUT;
+ return 0;
+ }
+ // hang forever? - according to spec, until interuppted by signal
+ TRequestStatus req = KRequestPending;
+ User::WaitForRequest(req);
+ }
+
+ // Now prepare to issue the asynchronous requests.
+ TRequestStatus** reqarray;
+ TRequestStatus* reqobjarray;
+
+ // Create the array of TRequestStatus objects
+ reqobjarray = (TRequestStatus *) Alloc((numReqs + (timeout ? 1 : 0)) * sizeof(TRequestStatus));
+ if (!reqobjarray)
+ {
+ anErrno = ENOMEM;
+ return -1;
+ }
+
+ reqarray = (TRequestStatus **) Alloc((numReqs+arraycount + (timeout ? 1 : 0)) * sizeof(TRequestStatus*));
+ if (!reqarray)
+ {
+ Free(reqobjarray);
+ anErrno = ENOMEM;
+ return -1;
+ }
+
+ // Append all the created TRequestStatus objects to the array
+ for (int i = 0; i<numReqs; i++)
+ {
+ reqarray[i] = &reqobjarray[i];
+ }
+
+ // Append the array of TRequestStatus passed in waitarray to the array
+ for (int i = numReqs, j=0; i<numReqs+arraycount; i++, j++)
+ {
+ reqarray[i] = &waitarray[j];
+ }
+
+ if (timeout)
+ {
+ // Append the TRequestStatus used for timer to the array
+ reqarray[numReqs+arraycount] = &reqobjarray[numReqs];
+ }
+
+ TInt *reqfds = (TInt *)Alloc(numReqs * sizeof(TInt));
+ if (!reqfds)
+ {
+ Free(reqarray);
+ Free(reqobjarray);
+ anErrno = ENOMEM;
+ return -1;
+ }
+
+ // Reset numReqs. We will use it to keep track of how many objects in the
+ // reqarray are valid requests.
+ numReqs = 0;
+
+ // Used to detect one request gathered when this code reaches WaitForNReqs
+ TBool onedown = EFalse;
+
+ // define the RTimer here to work-around a GCC warning
+ RTimer timer;
+ if (timeout)
+ {
+ // Create the timer to handle the timeout
+ err = timer.CreateLocal();
+ if (err != KErrNone)
+ {
+ Free(reqarray);
+ Free(reqobjarray);
+ Free(reqfds);
+ return MapError(err, anErrno);
+ }
+ }
+
+ // Start processing requested-for events
+ for (int i = 0; i < maxfd; ++i)
+ {
+ TUint events = 0;
+
+ if (readfds && FD_ISSET(i, readfds))
+ {
+ events = EReadyForReading;
+ }
+
+ if (writefds && FD_ISSET(i, writefds))
+ {
+ events |= EReadyForWriting;
+ }
+
+ if (exceptfds && FD_ISSET(i, exceptfds))
+ {
+ events |= EAnyException;
+ }
+
+ if (!events)
+ {
+ continue;
+ }
+
+ if (iFids.At(i, fdesc) == KErrNone)
+ {
+ fdesc->TweakWatchedEvents(events);
+ err = fdesc->NotifyActivity(events, *reqarray[numReqs], timeout);
+ if (err == KErrCompletion)
+ {
+ // No async call was issued. Try a Poll
+ TInt ready = fdesc->Poll(events);
+ if (ready & EReadyForReading)
+ {
+ FD_SET(i, &retreadfds);
+ ++nDescriptorsSet;
+ }
+ if (ready & EReadyForWriting)
+ {
+ FD_SET(i, &retwritefds);
+ ++nDescriptorsSet;
+ }
+ if (ready & EAnyException)
+ {
+ FD_SET(i, &retexceptfds);
+ ++nDescriptorsSet;
+ }
+ break;
+ }
+ else if (err != KErrNone)
+ {
+ // Notification registration failed. Cleanup and return.
+ nDescriptorsSet = MapError(err, anErrno);
+ break;
+ }
+ else
+ {
+ // Issued an asynchronus request. Increment valid requests count.
+ reqfds[numReqs++] = i;
+ }
+ }
+ }
+
+ if (err != KErrNone)
+ {
+ if (timeout)
+ {
+ timer.Close();
+ }
+ for(TInt i= 0; i < numReqs; i++)
+ {
+ if (iFids.At(reqfds[i], fdesc) != KErrNone)
+ {
+ continue;
+ }
+ fdesc->CancelNotify();
+ }
+ goto bailout;
+ }
+
+ if (timeout)
+ {
+ timer.After(*reqarray[numReqs+arraycount], timeout);
+ // Wait for any request to complete
+ CLocalSystemInterface::WaitForNRequest(*reqarray, numReqs+arraycount+1);
+ if( (*reqarray[numReqs+arraycount]).Int() == KRequestPending)
+ {
+ // The timer hasn't fired yet.
+ timer.Cancel();
+ }
+ else
+ {
+ anErrno = ETIMEDOUT;
+ }
+ timer.Close();
+ // No need to set onedown to True as numReqs does not include the Timer request
+ }
+ else
+ {
+ CLocalSystemInterface::WaitForNRequest(*reqarray, numReqs+arraycount);
+ // Completion Status of one request has been gathered
+ onedown = ETrue;
+ }
+
+ for (int i = 0; i < numReqs; ++i)
+ {
+ if (iFids.At(reqfds[i], fdesc) != KErrNone)
+ {
+ continue;
+ }
+
+ if ( (*reqarray[i]).Int() != KRequestPending )
+ {
+ TInt readyevents = fdesc->TweakReadyEvents((*reqarray[i]).Int());
+ if (readfds && FD_ISSET(reqfds[i], readfds) && (readyevents & EReadyForReading) )
+ {
+ FD_SET(reqfds[i], &retreadfds);
+ ++nDescriptorsSet;
+ }
+ if(writefds && FD_ISSET(reqfds[i], writefds) && (readyevents & EReadyForWriting) )
+ {
+ FD_SET(reqfds[i], &retwritefds);
+ ++nDescriptorsSet;
+ }
+ if(exceptfds && FD_ISSET(reqfds[i], exceptfds) && (readyevents & EAnyException))
+ {
+ FD_SET(reqfds[i], &retexceptfds);
+ ++nDescriptorsSet;
+ }
+ }
+ else
+ {
+ //Cancel all other requests.
+ fdesc->CancelNotify();
+ }
+ }
+
+ if (readfds)
+ {
+ FD_COPY(&retreadfds, readfds);
+ }
+
+ if (writefds)
+ {
+ FD_COPY(&retwritefds, writefds);
+ }
+
+ if (exceptfds)
+ {
+ FD_COPY(&retexceptfds, exceptfds);
+ }
+
+ bailout:
+
+ if (onedown && numReqs)
+ {
+ --numReqs;
+ }
+ // consume all completed/cancelled requests
+ while(numReqs--)
+ {
+ User::WaitForAnyRequest();
+ }
+
+ Free(reqarray);
+ Free(reqobjarray);
+ Free(reqfds);
+ return nDescriptorsSet;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::system
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::system(const wchar_t* aCmd, const wchar_t* aCmdArg, int& anErrno)
+ {
+ return iFids.system(aCmd, aCmdArg, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::posix_spawn
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::posix_spawn(int* pid, const wchar_t* wpath,
+ const posix_spawn_file_actions_t* file_actions,
+ const posix_spawnattr_t* attrp,
+ const wchar_t* wargs,
+ wchar_t** wenvp)
+ {
+ return iFids.posix_spawn(pid, wpath, file_actions, attrp, wargs, wenvp);
+ }
+
+#ifdef SYMBIAN_OE_POSIX_SIGNALS
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::kill
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::kill(pid_t pid, int sig , int& anErrno)
+ {
+ EnsureSignalsInitialized();
+
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ TInt err = KErrArgument;
+ TProcessId lPid(pid);
+ RProcess lTargetProcess;
+
+ if(pid <= 0)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(lTargetProcess.Open(lPid) != KErrNone)
+ {
+ anErrno = ESRCH;
+ return -1;
+ }
+ else
+ {
+ lTargetProcess.Close();
+ }
+
+ if(sig == 0)
+ {
+ return MapError(KErrNone, anErrno);
+ }
+
+ if(sig < 1 || sig > SIGRTMAX)
+ {
+ return MapError(err, anErrno); // check for linux return value. standard says != 0
+ }
+
+ err = iSignalSession.SendSignal(pid,sig);
+ return MapError(err, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::raise
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::raise(int sig , int& anErrno)
+ {
+ EnsureSignalsInitialized();
+
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ TInt err = KErrArgument;
+ if(sig < 1 || sig > SIGRTMAX)
+ {
+ return MapError(err, anErrno); // check for linux return value. standard says != 0
+ }
+ // mutex protect
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::ESignal;
+ lMsg.mSignal = (TUint8)sig;
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lMsg.Marshall(lMsgBuf);
+
+ err = iSignalWritePipe.Write(lMsgBuf,KSigMsgLength);
+ if(err >= 0)
+ return MapError(KErrNone,anErrno);
+ else
+ return MapError(err, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigqueue
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigqueue(pid_t pid, int sig, const union sigval val, int& anErrno)
+ {
+ EnsureSignalsInitialized();
+
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ TInt err = KErrArgument;
+
+ TProcessId lPid(pid);
+ RProcess lTargetProcess;
+ if(lTargetProcess.Open(lPid) != KErrNone)
+ {
+ anErrno = ESRCH;
+ return -1;
+ }
+ else
+ {
+ lTargetProcess.Close();
+ }
+
+ if(sig == 0)
+ {
+ return MapError(KErrNone, anErrno);
+ }
+
+ if(sig < 1 || sig > SIGRTMAX)
+ {
+ return MapError(err, anErrno); // check for linux return value. standard says != 0
+ }
+
+ err = iSignalSession.SendSignalValue(pid,sig,val.sival_int);
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigfillset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigfillset(sigset_t *set, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(set == 0)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_FILL_SIGSET(*set);
+
+ return MapError(KErrNone, anErrno);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigaddset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigaddset(sigset_t *set, int signo, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(signo < 1 || signo > SIGRTMAX || set == 0)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_ADD_SIGNAL_TO_SET(signo,*set);
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigdelset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigdelset(sigset_t *set, int signo, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(signo < 1 || signo > SIGRTMAX || set == 0)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_REMOVE_SIGNAL_FROM_SET(signo,*set);
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigismember
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigismember(const sigset_t *set, int signo, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(signo < 1 || signo > SIGRTMAX || set == 0)
+ return MapError(KErrArgument, anErrno);
+
+ if(SIG_SIGNAL_PRESENT_IN_SIGSET(signo,*set))
+ return 1;
+ else
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigandset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigandset(sigset_t * set, const sigset_t * left, const sigset_t * right, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(set == 0 || left == 0 || right == 0)
+ return MapError(KErrArgument, anErrno);
+
+ *set = *left & *right;
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigorset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigorset(sigset_t * set, const sigset_t * left, const sigset_t * right, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(set == 0 || left == 0 || right == 0)
+ return MapError(KErrArgument, anErrno);
+
+ *set = *left | *right;
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigisemptyset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigisemptyset(const sigset_t * set, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(set == 0)
+ return MapError(KErrArgument, anErrno);
+
+ anErrno = 0;
+ if(SIG_ISEMPTY_SIGSET(*set))
+ return 1;
+ else
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigemptyset
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigemptyset(sigset_t * set, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ if(set == 0)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_EMPTY_SIGSET(*set);
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigprocmask
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigprocmask(int how, const sigset_t *set, sigset_t *oset, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ TUint64 lOldMask = iSigMask;
+ TBool lIsUnblocked = EFalse;
+
+ if(oset)
+ {
+ *oset = (sigset_t)iSigMask;
+ }
+
+ if(set)
+ {
+ switch(how)
+ {
+ case SIG_BLOCK:
+ iSigMask |= (TUint64)*set;
+ break;
+ case SIG_SETMASK:
+ iSigMask = (TUint64)*set;
+ lIsUnblocked = ETrue;
+ break;
+ case SIG_UNBLOCK:
+ iSigMask &= ~(TUint64)*set;
+ lIsUnblocked = ETrue;
+ break;
+ default:
+ return MapError(KErrArgument, anErrno);
+ }
+ }
+
+ // unsetting the bits of signals that cannot be blocked
+ // no error is to be thrown in this case
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGKILL,iSigMask);
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGSTOP,iSigMask);
+
+ if(lIsUnblocked)
+ {
+ TUint64 lDiffSet = (lOldMask & (~iSigMask));
+ if(lDiffSet != 0)
+ {
+ TInt lIdx = 0;
+ for(lIdx = 1;lIdx <= SIGRTMAX;lIdx++)
+ {
+ if(SIG_SIGNAL_PRESENT_IN_SIGSET(lIdx,lDiffSet))
+ {
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::EDequeueSignal;
+ lMsg.mSignal = (TUint8)lIdx;
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lMsg.Marshall(lMsgBuf);
+ iSignalWritePipe.Write(lMsgBuf,KSigMsgLength);
+
+ }
+ }
+ // scan and dequeue
+ }
+ }
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sighold
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sighold(int signo, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ if(signo < 1 || signo > SIGRTMAX)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_ADD_SIGNAL_TO_SET(signo,iSigMask);
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGKILL,iSigMask);
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGSTOP,iSigMask);
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigrelse
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigrelse(int signo, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+ TUint64 lPrevMask = iSigMask;
+
+ if(signo < 1 || signo > SIGRTMAX)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_REMOVE_SIGNAL_FROM_SET(signo,iSigMask);
+
+ if(lPrevMask != iSigMask)
+ {
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::EDequeueSignal;
+ lMsg.mSignal = (TUint8)signo;
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lMsg.Marshall(lMsgBuf);
+ iSignalWritePipe.Write(lMsgBuf,KSigMsgLength);
+ }
+
+ return MapError(KErrNone, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigpause
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigpause(int signo, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ TUint64 lPrevMask = iSigMask;
+ TUint64 lWaitSet = 0;
+ TSignalMessage lMsg;
+
+ if(signo < 1 || signo > SIGRTMAX)
+ return MapError(KErrArgument, anErrno);
+
+ SIG_REMOVE_SIGNAL_FROM_SET(signo,iSigMask);
+ SIG_ADD_SIGNAL_TO_SET(signo,lWaitSet);
+
+ SigWaitInternal(lWaitSet,&lMsg,0);
+
+ iSigMask = lPrevMask;
+
+ HandleSignal(lMsg,ETrue);
+
+ anErrno = EINTR;
+ return -1;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigwait
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigwait(const sigset_t *set, int *sig, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ return ENOTSUP;
+ }
+
+ EnsureSignalsInitialized();
+
+ anErrno = anErrno; // to supress unused arg warning. sigwait doesn't set errno, it returns it.
+
+ if(set == 0)
+ return EINVAL;
+
+ if(SIG_ISEMPTY_SIGSET(*set))
+ return EINVAL;
+
+ TUint64 lTemp = *set;
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGKILL,lTemp);
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGSTOP,lTemp);
+ if(lTemp == 0 && !SIG_ISEMPTY_SIGSET(set))
+ return 0;
+
+ TInt lRetVal = KErrNone;
+ TSignalMessage lMsg;
+ lRetVal = SigWaitInternal((TUint64)*set,&lMsg,0);
+ if(lRetVal == KErrNone)
+ {
+ if(lMsg.mType == TSignalMessage::ESignal)
+ {
+ if(sig)
+ *sig = lMsg.mSignal;
+ }
+ else if(lMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ if(sig)
+ *sig = lMsg.mSigVal.mSignal;
+ }
+ else if(lMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ if(sig)
+ *sig = lMsg.mRtSignal.mSignal;
+ }
+ }
+ else
+ {
+ return EINVAL;
+ }
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigtimedwait
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigtimedwait(const sigset_t *set,
+ siginfo_t *info, const struct timespec *timeout, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ TBool lTimeCheckFailed = EFalse;
+
+ EnsureSignalsInitialized();
+
+ if(set == 0 || timeout == 0)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+
+ if(SIG_ISEMPTY_SIGSET(*set))
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+
+ if(timeout->tv_sec == 0 && timeout->tv_nsec == 0)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+
+ if( (timeout->tv_sec*1000*1000 > 0x7FFFFFFF) || // 0x7FFFFFFF (maximum positive value of int32)
+ (timeout->tv_sec < 0) ||
+ (timeout->tv_nsec >= 1000000000) ||
+ (timeout->tv_nsec < 0) )
+ {
+ lTimeCheckFailed = ETrue;
+ }
+
+ TUint64 lTemp = *set;
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGKILL,lTemp);
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGSTOP,lTemp);
+ if(lTemp == 0 && !SIG_ISEMPTY_SIGSET(set))
+ return 0;
+
+ TInt lTimeout = timeout->tv_sec*1000*1000 + timeout->tv_nsec/1000;
+ if(lTimeout < 0)
+ {
+ lTimeCheckFailed = ETrue;
+ }
+
+ TInt lRetVal = KErrNone;
+ TInt lSigNum = 0;
+ TSignalMessage lMsg;
+
+ lRetVal = SigWaitInternal((TUint64)*set,&lMsg,lTimeout,lTimeCheckFailed);
+
+ if(lRetVal == KErrNone)
+ {
+ if(lMsg.mType == TSignalMessage::ESignal)
+ {
+ lSigNum = lMsg.mSignal;
+ if(info)
+ {
+ info->si_signo = lSigNum;
+ info->si_value.sival_int = 0;
+ }
+ }
+ else if(lMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ lSigNum = lMsg.mSigVal.mSignal;
+ if(info)
+ {
+ info->si_signo = lSigNum;
+ info->si_value.sival_int = (int)lMsg.mSigVal.mValue;
+ }
+ }
+ else if(lMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ lSigNum = lMsg.mRtSignal.mSignal;
+ if(info)
+ {
+ info->si_signo = lSigNum;
+ info->si_value.sival_int = 0;
+ }
+ }
+ }
+ else if (lRetVal == KErrTimedOut)
+ {
+ anErrno = EAGAIN;
+ return -1;
+ }
+ else
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+ return lSigNum;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigwaitinfo
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigwaitinfo(const sigset_t *set, siginfo_t *info, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ if(set == 0)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+
+ if(SIG_ISEMPTY_SIGSET(*set))
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+
+ TUint64 lTemp = *set;
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGKILL,lTemp);
+ SIG_REMOVE_SIGNAL_FROM_SET(SIGSTOP,lTemp);
+ if(lTemp == 0 && !SIG_ISEMPTY_SIGSET(set))
+ return 0;
+
+ TInt lRetVal = KErrNone;
+ TInt lSigNum = 0;
+ TSignalMessage lMsg;
+
+ lRetVal = SigWaitInternal((TUint64)*set,&lMsg,0);
+
+ if(lRetVal == KErrNone)
+ {
+ if(lMsg.mType == TSignalMessage::ESignal)
+ {
+ lSigNum = lMsg.mSignal;
+ if(info)
+ {
+ info->si_signo = lSigNum;
+ info->si_value.sival_int = 0;
+ }
+ }
+ else if(lMsg.mType == TSignalMessage::ESignalValuePair)
+ {
+ lSigNum = lMsg.mSigVal.mSignal;
+ if(info)
+ {
+ info->si_signo = lSigNum;
+ info->si_value.sival_int = (int)lMsg.mSigVal.mValue;
+ }
+ }
+ else if(lMsg.mType == TSignalMessage::ERtTimerSignal)
+ {
+ lSigNum = lMsg.mRtSignal.mSignal;
+ if(info)
+ {
+ info->si_signo = lSigNum;
+ info->si_value.sival_int = 0;
+ }
+ }
+ else
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+ }
+
+ return lSigNum;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigaction
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigaction(int aSigNum, const struct sigaction *act, struct sigaction *oact, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ if(aSigNum < 1 || aSigNum > SIGRTMAX || aSigNum == SIGKILL || aSigNum == SIGSTOP)
+ {
+ return MapError(KErrArgument,anErrno);
+ }
+
+ if(act && (act->sa_flags & (SA_NOCLDSTOP | SA_ONSTACK | SA_RESTART| SA_NOCLDWAIT))) //Whar abt SA_NODEFER
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ iSigHandlerMutex.Wait();
+ if(oact)
+ {
+ if( (iSigActions[aSigNum-1].iSigFlags & SA_SIGINFO)
+ && iSigActions[aSigNum-1].iSigAction)
+ {
+ oact->sa_flags = iSigActions[aSigNum-1].iSigFlags;
+ oact->sa_sigaction = iSigActions[aSigNum-1].iSigAction;
+ }
+ else
+ {
+ oact->sa_flags = iSigActions[aSigNum-1].iSigFlags;
+ oact->sa_handler = iSigActions[aSigNum-1].iSigHandler;
+ }
+ }
+
+ if(act)
+ {
+ if(act->sa_flags & SA_SIGINFO)
+ {
+ iSigActions[aSigNum-1].iSigAction = act->sa_sigaction;
+ iSigActions[aSigNum-1].iSigFlags = act->sa_flags;
+ }
+ else
+ {
+ iSigActions[aSigNum-1].iSigHandler = act->sa_handler;
+ iSigActions[aSigNum-1].iSigAction = 0;
+ iSigActions[aSigNum-1].iSigFlags = act->sa_flags;
+ }
+ }
+ iSigHandlerMutex.Signal();
+
+ return MapError(KErrNone,anErrno);
+
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigset
+// -----------------------------------------------------------------------------
+//
+TSignalHandler CLocalSystemInterface::sigset(int aSigNum, TSignalHandler disp, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return SIG_ERR;
+ }
+
+ TUint64 lOldMask = iSigMask;
+ EnsureSignalsInitialized();
+
+ if(aSigNum < 1 || aSigNum > SIGRTMAX || aSigNum == SIGKILL || aSigNum == SIGSTOP)
+ {
+ anErrno = EINVAL;
+ return SIG_ERR;
+ }
+ TSignalHandler lOldHandler = iSigActions[aSigNum-1].iSigHandler;
+
+ if(disp == SIG_HOLD)
+ {
+ SIG_ADD_SIGNAL_TO_SET(aSigNum,iSigMask);
+ }
+ else
+ {
+ iSigHandlerMutex.Wait();
+ iSigActions[aSigNum-1].iSigHandler = disp;
+ iSigActions[aSigNum-1].iSigAction = 0;
+ iSigActions[aSigNum-1].iSigFlags = 0;
+ iSigHandlerMutex.Signal();
+ SIG_REMOVE_SIGNAL_FROM_SET(aSigNum,iSigMask);
+ }
+
+ if(SIG_SIGNAL_PRESENT_IN_SIGSET(aSigNum,lOldMask))
+ return SIG_HOLD;
+ else
+ return lOldHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::bsd_signal
+// -----------------------------------------------------------------------------
+//
+TSignalHandler CLocalSystemInterface::bsd_signal(int aSigNum, TSignalHandler aFunc,int& anErrno)
+ {
+ return signal(aSigNum,aFunc,anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::signal
+// -----------------------------------------------------------------------------
+//
+TSignalHandler CLocalSystemInterface::signal(int aSigNum, TSignalHandler aFunc,int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return SIG_ERR;
+ }
+
+ EnsureSignalsInitialized();
+
+ if(aSigNum < 1 || aSigNum > SIGRTMAX || aSigNum == SIGKILL || aSigNum == SIGSTOP)
+ {
+ anErrno = EINVAL;
+ return SIG_ERR;
+ }
+
+ iSigHandlerMutex.Wait();
+ TSignalHandler lOldHandler = iSigActions[aSigNum-1].iSigHandler;
+ iSigActions[aSigNum-1].iSigHandler = aFunc;
+ iSigActions[aSigNum-1].iSigAction = 0;
+ iSigActions[aSigNum-1].iSigFlags = 0;
+ iSigHandlerMutex.Signal();
+ return lOldHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigignore
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigignore(int aSigNum, int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ if(aSigNum < 1 || aSigNum > SIGRTMAX || aSigNum == SIGKILL || aSigNum == SIGSTOP)
+ {
+ anErrno = EINVAL;
+ return -1;
+ }
+
+ iSigHandlerMutex.Wait();
+ iSigActions[aSigNum-1].iSigHandler = SIG_IGN;
+ iSigActions[aSigNum-1].iSigAction = 0;
+ iSigActions[aSigNum-1].iSigFlags = 0;
+ iSigHandlerMutex.Signal();
+ return 0;
+ }
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::sigpending
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::sigpending(sigset_t *set,int& anErrno)
+ {
+ if(!iSignalsInitialized)
+ {
+ anErrno = ENOTSUP;
+ return -1;
+ }
+
+ EnsureSignalsInitialized();
+
+ if(set == 0)
+ {
+ anErrno = EFAULT;
+ return -1;
+ }
+
+ SIG_EMPTY_SIGSET(*set);
+
+ TInt lIdx = 0;
+
+ for(lIdx = 0;lIdx < iBlockedSigArray.Count(); lIdx++)
+ {
+ TUint8 lSigNum = 0;
+ if(iBlockedSigArray[lIdx].mType == TSignalMessage::ESignal)
+ lSigNum = iBlockedSigArray[lIdx].mSignal;
+ else if(iBlockedSigArray[lIdx].mType == TSignalMessage::ESignalValuePair)
+ lSigNum = iBlockedSigArray[lIdx].mSigVal.mSignal;
+ else if(iBlockedSigArray[lIdx].mType == TSignalMessage::ERtTimerSignal)
+ lSigNum = iBlockedSigArray[lIdx].mRtSignal.mSignal;
+ SIG_ADD_SIGNAL_TO_SET(lSigNum,*set);
+ }
+
+ return MapError(KErrNone,anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::alarm
+// -----------------------------------------------------------------------------
+//
+unsigned int CLocalSystemInterface::alarm(unsigned int seconds)
+ {
+ if(!iSignalsInitialized)
+ {
+ return 0;
+ }
+
+ EnsureSignalsInitialized();
+
+ TTime lCurrentTime;
+ TTimeIntervalSeconds lTimeLapse;
+
+ unsigned int lTimeLeft = 0;
+
+ if(iIsTimerActive)
+ {
+ lCurrentTime.HomeTime();
+ lCurrentTime.SecondsFrom(iAlarmStartTime,lTimeLapse);
+ lTimeLeft = iCurrentTimeout - lTimeLapse.Int();
+ if((int)lTimeLeft < 0)
+ lTimeLeft = 0;
+ }
+
+ iCurrentTimeout = seconds;
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::EAlarmRegistration;
+ lMsg.mTimeOut = seconds;
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lMsg.Marshall(lMsgBuf);
+ iSignalWritePipe.Write(lMsgBuf,KSigMsgLength);
+
+ return lTimeLeft;
+ }
+
+
+#ifdef SYMBIAN_OE_LIBRT
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::FindTimer
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::FindTimer(const TInt& aTimerId)
+ {
+ iTimerOverrunsMutex.Wait();
+
+ TInt lIndex = KErrNotFound;
+ TInt lTimerCnt = iTimerOverruns.Count();
+ for(TInt lIdx = 0; lIdx < lTimerCnt; lIdx++)
+ {
+ if(iTimerOverruns[lIdx].iTimerId == aTimerId)
+ {
+ lIndex = lIdx;
+ break;
+ }
+ }
+
+ iTimerOverrunsMutex.Signal();
+ return lIndex;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::AddTimer
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::AddTimer(const TInt& aTimerId)
+ {
+ TInt err;
+ if (FindTimer(aTimerId) >= 0)
+ {
+ err = KErrNone;
+ }
+ else
+ {
+ TOverrun lOverrun(aTimerId);
+ iTimerOverrunsMutex.Wait();
+ RHeap* oHeap = User::SwitchHeap(iPrivateHeap);
+ err = iTimerOverruns.Append(lOverrun);
+ User::SwitchHeap(oHeap);
+ if(!err)
+ {
+ iTimerOverruns[iTimerOverruns.Count()-1].iTimerId = aTimerId;
+ }
+
+ iTimerOverrunsMutex.Signal();
+ }
+
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::DeleteTimer
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::DeleteTimer(const TInt& aTimerId)
+ {
+ TInt lRet = FindTimer(aTimerId);
+ if(lRet >= 0)
+ {
+ iTimerOverrunsMutex.Wait();
+ RHeap* oHeap = User::SwitchHeap(iPrivateHeap);
+ iTimerOverruns.Remove(lRet);
+ User::SwitchHeap(oHeap);
+ iTimerOverrunsMutex.Signal();
+
+ return KErrNone;
+ }
+
+ return lRet;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::IncrementOverrun
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::IncrementOverrun(const TInt& aTimerId)
+ {
+ TInt lRet = FindTimer(aTimerId);
+ if(lRet >= 0)
+ {
+ iTimerOverrunsMutex.Wait();
+ iTimerOverruns[lRet].Overruns++;
+ iTimerOverrunsMutex.Signal();
+ return iTimerOverruns[lRet].Overruns;
+ }
+
+ return lRet;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::ResetOverrun
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::ResetOverrun(const TInt& aTimerId)
+ {
+ TInt lRet = FindTimer(aTimerId);
+ if(lRet >= 0)
+ {
+ iTimerOverrunsMutex.Wait();
+ iTimerOverruns[lRet].Overruns = 0;
+ iTimerOverrunsMutex.Signal();
+ return KErrNone;
+ }
+
+ return KErrNotFound;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::Overrun
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::Overrun(const TInt& aTimerId)
+ {
+ TInt lRet = FindTimer(aTimerId);
+ if(lRet >= 0)
+ {
+ return iTimerOverruns[lRet].Overruns;
+ }
+
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::RaiseTimerSignal
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CLocalSystemInterface::RaiseTimerSignal(int sig, int timerid)
+ {
+ EnsureSignalsInitialized();
+
+ TInt err = KErrArgument;
+ if(sig < 1 || sig > SIGRTMAX)
+ {
+ return err;
+ }
+ // mutex protect
+ TSignalMessage lMsg;
+ lMsg.mType = TSignalMessage::ERtTimerSignal;
+ lMsg.mRtSignal.mSignal = (TUint8)sig;
+ lMsg.mRtSignal.mTimerId = timerid;
+ TBuf8<KSigMsgLength> lMsgBuf;
+ lMsg.Marshall(lMsgBuf);
+
+ err = iSignalWritePipe.WriteBlocking(lMsgBuf,KSigMsgLength);
+ if(err >= 0)
+ return KErrNone;
+
+ return err;
+ }
+
+#endif //SYMBIAN_OE_LIBRT
+
+#endif // SYMBIAN_OE_POSIX_SIGNALS
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::GetDirName
+// Implementation for GetDirName
+// This will return the name of the directory corresponding to the aFid
+// This wont set any error code in case of error.
+// Returns the name on success else NULL
+// -----------------------------------------------------------------------------
+//
+const wchar_t* CLocalSystemInterface::GetDirName (int aFid)
+ {
+ //Get the CFileDescBase at the index aFid
+ CFileDescBase* desc = NULL;
+ TInt err = iFids.At(aFid, desc);
+ if ( !err )
+ {
+ //Cast it back to CDirectoryDesc
+ CDirectoryDesc* dirDesc = static_cast<CDirectoryDesc*> (desc);
+ return dirDesc->GetDirName();
+ }
+ return (const wchar_t*)NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::Truncate
+// Implementation for Truncate
+// This will Truncate a file represented by aFid
+// Returns the success/error code on completion
+// -----------------------------------------------------------------------------
+//
+EXPORT_C int CLocalSystemInterface::Truncate(int aFid, off_t anOffset, int& anErrno)
+ {
+ TInt err = KErrArgument;
+#if defined(SYMBIAN_OE_LARGE_FILE_SUPPORT) && !defined(SYMBIAN_OE_NO_LFS)
+ off_t offset = anOffset;
+#else
+ TInt offset = (TInt)anOffset;
+#endif //SYMBIAN_OE_LARGE_FILE_SUPPORT && !SYMBIAN_OE_NO_LFS
+ //Proceed only if offset is non-negetive number
+ if ( offset >= 0 )
+ {//Get the CFileDescBase at the index aFid
+ CFileDescBase* desc = NULL;
+ err = iFids.At(aFid, desc);
+ if ( !err )
+ {
+ err = desc->Truncate(offset);
+ if( err == KErrAccessDenied )
+ {
+ //Ensure that, it will set errno as EINVAL
+ err = KErrArgument;
+ }
+ }
+ }
+
+ return MapError(err, anErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::GetDesc
+// Implementation for GetDesc
+// This will return the CFileDescBase object corresponding to aFid
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CFileDescBase* CLocalSystemInterface::GetDesc(int aFid)
+ {
+ CFileDescBase* fileDesc = NULL;
+ //coverity[unchecked_value]
+ iFids.At(aFid, fileDesc);
+ return fileDesc;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::FileSession
+// This will return the file session
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RFs& CLocalSystemInterface::FileSession()
+ {
+ return iFs;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::CommServSession
+// This will return the communication server session
+// -----------------------------------------------------------------------------
+//
+RCommServ& CLocalSystemInterface::CommServSession()
+ {
+ return iCs;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::SockServSession
+// This will return the socket server session
+// -----------------------------------------------------------------------------
+//
+RSocketServ& CLocalSystemInterface::SockServSession()
+ {
+ return iSs;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::Alloc
+// Dynamic Memory related APIs
+// Allocates memory in the private heap
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void* CLocalSystemInterface::Alloc(size_t aNBytes)
+ {
+ return iPrivateHeap->AllocZ(aNBytes);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::ReAlloc
+// Dynamic Memory related APIs
+// Allocates memory in the private heap
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void* CLocalSystemInterface::ReAlloc(void* aPtr, size_t aNBytes)
+ {
+ return iPrivateHeap->ReAlloc(aPtr, aNBytes);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::Free
+// Dynamic Memory related APIs
+// Frees memory in the private heap
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLocalSystemInterface::Free(void* aPtr)
+ {
+ iPrivateHeap->Free(aPtr);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::AllocTLD
+// Dynamic Memory related APIs
+// Allocates memory for the thread's TLD and cleans up TLD of dead threads
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void* CLocalSystemInterface::AllocTLD(TInt aSize)
+ {
+ // Allocate memory for reent structure on private heap
+ void* ptr = iPrivateHeap->AllocZ(aSize);
+
+ iTLDListLock.Wait();
+ RHeap* oheap = User::SwitchHeap(iPrivateHeap);
+
+ TThreadId caller = RThread().Id();
+ RThread thrd;
+
+ TInt idx = -1;
+
+ TInt tcount = iTLDInfoList.Count();
+
+ for (int i = 0; i < tcount; ++i)
+ {
+ TTLDInfo& tldinf = iTLDInfoList[i];
+
+ TInt ptrcount = tldinf.iPtrs.Count();
+
+ if (!ptrcount)
+ {
+ // This slot has already been freed. Save here?
+ idx = i;
+ continue;
+ }
+
+ TInt err = thrd.Open(tldinf.iTid);
+
+ if (err != KErrNone || thrd.ExitType() != EExitPending)
+ {
+ // This thread is dead. Bury it.
+ for (int j = 0; j < ptrcount; ++j)
+ {
+ iPrivateHeap->FreeZ(tldinf.iPtrs[j]);
+ }
+
+ (tldinf.iPtrs).Reset();
+
+ // this slot can be reused. Save here?
+ idx = i;
+ }
+ else
+ {
+ // Points to a live thread
+ if (tldinf.iTid == caller)
+ {
+ // This is the calling thread. We must save the TLD ptr here
+ idx = i;
+ }
+ }
+ }
+
+ // Only if the initial allocation succeded
+ if (ptr != NULL)
+ {
+ // No free slot. No cleaned-up slots.
+ if (idx == -1)
+ {
+ iTLDInfoList.Append(TTLDInfo(caller, ptr));
+ }
+ else
+ {
+ // Wouldn't hurt even if it is already set
+ iTLDInfoList[idx].iTid = caller;
+ iTLDInfoList[idx].iPtrs.Append(ptr);
+ }
+ }
+
+ User::SwitchHeap(oheap);
+ iTLDListLock.Signal();
+
+ return ptr;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::Heap
+//Return the private Heap memory
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RHeap* CLocalSystemInterface::Heap()
+ {
+ return iPrivateHeap;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::CommsSessionLock
+//Return the Comms Server Lock
+// -----------------------------------------------------------------------------
+//
+RFastLock& CLocalSystemInterface::CommsSessionLock()
+ {
+ return iCSLock;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::CommsSessionLock
+//Return reference to file table
+// -----------------------------------------------------------------------------
+//
+const CFileTable& CLocalSystemInterface::FileTable() const
+{
+return iFids;
+}
+
+// ---------------------------------------------------------------------------------
+// CLocalSystemInterface::WaitForNRequest
+// Wait for any one of the input asynchronous requests to complete
+// Used in lieu of User::WaitForNRequest because of need to support pre-Argus builds
+// ---------------------------------------------------------------------------------
+//
+void CLocalSystemInterface::WaitForNRequest(TRequestStatus aStatusArray[], TInt aNum)
+ {
+ if (aNum)
+ {
+ // used to keep count of requests we have not been asked to wait for
+ TInt nOther = -1;
+ TBool done = EFalse;
+
+ do
+ {
+ ++nOther;
+ User::WaitForAnyRequest();
+ for (TInt i = 0; i < aNum; ++i)
+ {
+ if (aStatusArray[i].Int() != KRequestPending)
+ {
+ done = ETrue;
+ break;
+ }
+ }
+ } while (!done);
+
+ if (nOther)
+ {
+ // Adjust the thread's signal semaphore to account for the requests
+ // we were not asked to wait for.
+ RThread thrd;
+ for (TInt i = 0; i < nOther; ++i)
+ {
+ thrd.RequestSignal();
+ }
+ }
+ }
+ }
+/*
+CLocalSystemInterface::AddToDirList
+Appends Open Directory handle to a RPointerArray array and retuns 0
+ */
+
+int CLocalSystemInterface::AddToDirList(DIR *aDir)
+ {
+ RHeap* oheap = User::SwitchHeap(iPrivateHeap);
+ TInt ret = iOpenDirList.Append(aDir);
+ User::SwitchHeap(oheap);
+ return ret;
+ }
+
+
+/*
+CLocalSystemInterface::RemoveFromDirList
+Remove the Directory handle from the array and closes the array.
+ */
+
+int CLocalSystemInterface::RemoveDirFromList(DIR* aDir)
+ {
+
+ TInt ret = iOpenDirList.Find(aDir);
+ if(ret != KErrNotFound)
+ {
+ RHeap* oheap = User::SwitchHeap(iPrivateHeap);
+ iOpenDirList.Remove(ret);
+ User::SwitchHeap(oheap);
+ }
+ return ret;
+ }
+
+
+
+/*
+TBool CLocalSystemInterface::ValidateInDirList
+Validates the Directory handle with the array and returns ETrue upon success
+else returns EFalse.
+ */
+
+int CLocalSystemInterface::FindInDirList(DIR* aDir)
+ {
+ return(iOpenDirList.Find(aDir));
+ }
+
+//
+//int CLocalSystemInterface::SetEcho(int aFd, TBool aEcho, int& aErrno)
+//
+//Set the echo flag of the suppported console abstractions matching
+//the given fd.
+//
+int CLocalSystemInterface::SetEcho(int aFd, TUint8 aEcho, int& aErrno)
+ {
+ return iFids.SetEcho(aFd, aEcho, aErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::ReadRecordFromIapTableL
+//
+// Helper function to read a record from the IAP table
+// -----------------------------------------------------------------------------
+//
+void CLocalSystemInterface::ReadRecordFromIapTableL(CCommsDbTableView* aView, TAccessPointRecord &aRecord)
+ {
+ aView->ReadUintL(TPtrC(COMMDB_ID), aRecord.iId);
+ aView->ReadTextL(TPtrC(COMMDB_NAME), aRecord.iName);
+ aView->ReadUintL(TPtrC(IAP_BEARER), aRecord.iBearer);
+ aView->ReadUintL(TPtrC(IAP_NETWORK), aRecord.iNetwork);
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::GetConnectionPreferencesL
+//
+// Get the connection preferences from an IAP name.
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::GetConnectionPreferencesL(TBuf<KCommsDbSvrMaxColumnNameLength> aIapName,
+ TCommDbConnPref &aConnPref)
+ {
+ TInt err = KErrNone;
+
+ //Open the database and create the IAP view.
+ CCommsDatabase *iApDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(iApDb);
+ iApDb->ShowHiddenRecords();
+ //The following pushes the view onto the cleanup stack
+ CCommsDbTableView *view = iApDb->OpenTableLC(TPtrC(IAP));
+
+ //Iterate through the records to find the matching entry
+ TAccessPointRecord apRecord;
+ err = view->GotoFirstRecord();
+ while (err == KErrNone)
+ {
+ //The following function will leave in case of error
+ ReadRecordFromIapTableL(view, apRecord);
+ if (aIapName == apRecord.iName)
+ break;
+
+ err = view->GotoNextRecord();
+ }
+
+ CleanupStack::PopAndDestroy(); //Free the view
+ CleanupStack::PopAndDestroy(iApDb); //Free the db itself
+
+ if(err != KErrNone) //Record not found
+ return KErrNotFound;
+
+ aConnPref.SetIapId(apRecord.iId);
+ aConnPref.SetNetId(apRecord.iNetwork);
+ aConnPref.SetBearerSet(apRecord.iBearer);
+ aConnPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+ aConnPref.SetDirection(ECommDbConnectionDirectionUnknown);
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::RestartDefConnection
+//
+// Helper function for the setdefaultif() API to restart the
+// default RConnection with the new settings.
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::StartDefConnection()
+ {
+ //Close the connection and re-open it with the new preferences
+ if(iDefConnection.SubSessionHandle() != 0)
+ iDefConnection.Close();
+
+ TInt err = iDefConnection.Open(iSs);
+ if( err != KErrNone )
+ return err;
+
+ err = iDefConnection.Start(*iDefConnPref);
+ if( err != KErrNone )
+ iDefConnection.Close();
+
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::setdefaultif
+//
+// Set the default interface for network operations
+// -----------------------------------------------------------------------------
+//
+int CLocalSystemInterface::setdefaultif(const struct ifreq* aIfReq)
+ {
+ //If the argument is NULL, close the existing connection
+ if(aIfReq == NULL )
+ {
+ // Obtain lock on the iDefConnection
+ iDefConnLock.Wait();
+ if(iDefConnection.SubSessionHandle() != 0)
+ iDefConnection.Close();
+ if( iDefConnPref )
+ {
+ switch( iDefConnPref->ExtensionId() )
+ {
+ case TConnPref::EConnPrefSnap:
+ {
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ delete (TCommSnapPref*)iDefConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ iDefConnPref = NULL;
+ }
+ break;
+
+ case TConnPref::EConnPrefCommDb:
+ {
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ delete (TCommDbConnPref*)iDefConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ iDefConnPref = NULL;
+ }
+ break;
+
+ default:
+ {
+ iDefConnLock.Signal();
+ // Unknown type of Connection Pref
+ return KErrUnknown;
+ }
+ }
+ }
+ // Release lock on the iDefConnection
+ iDefConnLock.Signal();
+ return KErrNone;
+ }
+
+ TPtrC8 namePtr((TText8*)aIfReq->ifr_name);
+ TBuf<KCommsDbSvrMaxColumnNameLength> name;
+ TInt err = CnvUtfConverter::ConvertToUnicodeFromUtf8(name,namePtr);
+ if( err != KErrNone )
+ return err;
+
+ if( iDefConnPref )
+ {
+ switch( iDefConnPref->ExtensionId() )
+ {
+ case TConnPref::EConnPrefSnap:
+ {
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ delete (TCommSnapPref*)iDefConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ iDefConnPref = NULL;
+ }
+ break;
+
+ case TConnPref::EConnPrefCommDb:
+ {
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ delete (TCommDbConnPref*)iDefConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ iDefConnPref = NULL;
+ }
+ break;
+
+ default:
+ {
+ // Unknown type of Connection Pref
+ return KErrUnknown;
+ }
+ }
+ }
+
+ // If the interface name is an empty string, the SNAP id is to be set
+ if(name.Length() == 0)
+ {
+ // Switch to backend heap
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ iDefConnPref = new TCommSnapPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ if( iDefConnPref == NULL )
+ {
+ return KErrNoMemory;
+ }
+ TCommSnapPref* snapprefptr = (TCommSnapPref*)iDefConnPref;
+ snapprefptr->SetSnap(aIfReq->ifr_ifru.snap_id);
+ return KErrNone;
+ }
+ else //Set the IAP name
+ {
+ CTrapCleanup *cleanupStack = NULL;
+ //Create a clean up stack if it is not existing.
+ if(User::TrapHandler() == NULL)
+ {
+ cleanupStack = CTrapCleanup::New(); //This will be deleted after use
+ if(cleanupStack == NULL)
+ return KErrNoMemory;
+ }
+
+ // Switch to backend heap
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ iDefConnPref = new TCommDbConnPref;
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ if( iDefConnPref == NULL )
+ {
+ if( cleanupStack != NULL )
+ delete cleanupStack;
+ return KErrNoMemory;
+ }
+ TRAP(err, (err = GetConnectionPreferencesL(name,*(TCommDbConnPref*)iDefConnPref)))
+
+ if( cleanupStack != NULL )
+ delete cleanupStack;
+
+ return err;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::GetDefaultConnection
+//
+// Function to get the default connection instance from backend.
+// The caller should check the handle before using the instance.
+// -----------------------------------------------------------------------------
+//
+RConnection& CLocalSystemInterface::GetDefaultConnection()
+ {
+ // If GetDefaultConnection is called without calling
+ // setdefaultif then the connection is not started
+ // Obtain lock on the iDefConnection
+ iDefConnLock.Wait();
+ if(iDefConnection.SubSessionHandle() == 0)
+ {
+ // iDefConnPref should not be NULL for starting the connection
+ if( iDefConnPref )
+ {
+ StartDefConnection();
+ }
+ }
+ // Release lock on the iDefConnection
+ iDefConnLock.Signal();
+ return iDefConnection;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::GetSessionPath
+//
+// Retrieves the cached session path from the backend
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::GetSessionPath(TDes& aPath)
+ {
+ if(aPath.MaxLength() < iSessionPath.Length())
+ return KErrArgument;
+
+ iSessionPathLock.Wait();
+ aPath.Copy(iSessionPath);
+ iSessionPathLock.Signal();
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::SaveSessionPath
+//
+// Caches the session path in the backend
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::SaveSessionPath(const TDesC& aPath)
+ {
+ if(aPath.Length() > KMaxFileName)
+ return KErrArgument;
+
+ iSessionPathLock.Wait();
+ iSessionPath.Copy(aPath);
+ iSessionPathLock.Signal();
+
+ return KErrNone;
+ }
+// -----------------------------------------------------------------------------
+// handleASelect(TAny* aPtr);
+// This function is called to handle aselect, aselect is implemented by
+// running select on a different thread, this function is the thread function
+// that is used for implementing aselect
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::handleaselect(TAny* aPtr)
+ {
+ int errval;
+ // Call select, when it returns signal the TRequestStatus
+ // Extract request info
+ TaselectRequestInfo *requestInfo = (TaselectRequestInfo *)aPtr;
+ RArray<TASelectRequest>& selectRequest = Backend()->ASelectRequest();
+ RFastLock& selectLock = Backend()->ASelectLock();
+ // Call select
+ TInt nDesReady = Backend()->select(requestInfo->iMaxFd, requestInfo->iReadFds,requestInfo->iWriteFds,requestInfo->iExceptFds, requestInfo->itvptr,errval);
+ // Open the main thread, this is required to signal it after processing
+ RThread mainThread;
+ TInt err = mainThread.Open(requestInfo->iId,EOwnerProcess);
+ if( err == KErrNone )
+ {
+ for ( TInt i=0; i<selectRequest.Count(); i++ )
+ {
+ if( selectRequest[i].iRequestStatus == requestInfo->iRequestStatus )
+ {
+ // Acquire a lock on the iSelectRequest object
+ selectLock.Wait();
+ // Switch to backend heap
+ RHeap* oldHeap = User::SwitchHeap(Backend()->Heap());
+ selectRequest.Remove(i);
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ // Release the lock
+ selectLock.Signal();
+ break;
+ }
+ }
+ // Check if select has failed
+ if( nDesReady == -1 )
+ {
+ // There is an error, we need to propogate the errno
+ // Convert errno to negative value
+ errval = errval * -1;
+ mainThread.RequestComplete(requestInfo->iRequestStatus,errval);
+ }
+ else
+ {
+ // Complete the request on the main thread and the TRequestStatus specified
+ // in the requestInfo
+ mainThread.RequestComplete(requestInfo->iRequestStatus,nDesReady);
+ }
+ mainThread.Close();
+ }
+ // Release the memory used for the TASelectRequestInfo
+ Backend()->Free(aPtr);
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLocalSystemInterface::CreateASelectThread
+// -----------------------------------------------------------------------------
+//
+TInt CLocalSystemInterface::CreateaselectThread(int maxfd, fd_set* readfds, fd_set* writefds,
+ fd_set* exceptfds, struct timeval* tvptr,
+ TRequestStatus* requeststatus, int& anErrno)
+ {
+ // Create a aselect request holder, this will be destroyed by the new thread#
+ // after processing
+ TaselectRequestInfo *requestInfo = (TaselectRequestInfo* )Backend()->Alloc(sizeof(TaselectRequestInfo));
+ // request info will be null if dynamic creation fails
+ if( !requestInfo )
+ {
+ anErrno = ENOMEM;
+ return -1;
+ }
+ // Set the aselect request parameters
+ RThread currentThread;
+ requestInfo->iId = currentThread.Id();
+ currentThread.Close();
+ // Fill the request struct
+ requestInfo->iMaxFd = maxfd;
+ requestInfo->iReadFds = readfds;
+ requestInfo->iWriteFds = writefds;
+ requestInfo->iExceptFds = exceptfds;
+ requestInfo->itvptr = tvptr;
+ requestInfo->iRequestStatus = requeststatus;
+ *(requestInfo->iRequestStatus) = KRequestPending;
+ RThread thread;
+ // We create an anonymous thread
+ TInt err = thread.Create(KNullDesC, CLocalSystemInterface::handleaselect, 4096, KMinHeapSize,
+ 256*KMinHeapSize, requestInfo);
+ if ( err != KErrNone )
+ {
+ anErrno = ENOMEM;
+ return -1;
+ }
+
+ // Create a aselect request object
+ TASelectRequest aselectrequest;
+ // retrive the service thread handle
+ aselectrequest.iThreadId = thread.Id();
+ // Store the TRequestStatus used for the request
+ aselectrequest.iRequestStatus = requeststatus;
+ // Obtain the lock
+ iASelectLock.Wait();
+ // Switch to backend heap
+ RHeap* oldHeap = User::SwitchHeap(iPrivateHeap);
+ // Append to the array
+ iASelectRequest.Append(aselectrequest);
+ // Switch back to old heap
+ User::SwitchHeap(oldHeap);
+ // Release the lock
+ iASelectLock.Signal();
+ // Execute the thread
+ thread.Resume();
+ // Close the handle
+ thread.Close();
+ return MapError(KErrNone, anErrno);
+ }
+