--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/openenvcore/backend/src/syscall/handlefms.cpp Fri Jun 04 16:20:51 2010 +0100
@@ -0,0 +1,674 @@
+/*
+* Copyright (c) 2005-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:
+*
+*/
+
+// connectors for re-entrant networking system calls
+
+#include <sys/errno.h>
+#include "sysreent.h"
+#include "aeselectreent.h"
+#include <unistd.h>
+#include <fcntl.h> // for open()
+#include <sys/ioctl.h>
+#include <stdarg.h>
+#include <utf.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <spawn.h>
+#include <charconv.h>
+#include "sys/stat.h"
+#include <wchar.h>
+#include "systemspecialfilercg.h"
+#include "link.h"
+#include "errno.h"
+
+#include "sysif.h"
+#include "lposix.h"
+
+
+
+#define MAXPATHLEN 256 /* E32STD.H: KMaxFullName */
+
+TInt __EPOC32_WDIR::UpdateNarrow()
+ {
+ return -1; //this is not supported.
+ }
+
+TInt __EPOC32_DIR::UpdateNarrow()
+ {
+ //update the narrow one
+
+ TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(iCurrentNarrowName, iCurrentName);
+ if (ret >= 0)
+ {
+ iCurrentNarrow.d_namlen=(short)iCurrentNarrowName.Length();
+ memcpy(iCurrentNarrow.d_name,iCurrentNarrowName.PtrZ(),iCurrentNarrowName.Length() + 1);
+ }
+ return ret;
+ }
+
+__EPOC32_WDIR::~__EPOC32_WDIR()
+ {
+ delete iPath;
+ delete iEntries;
+ }
+
+TInt __EPOC32_WDIR::Open(const wchar_t* _path,int* aErrno)
+ {
+ TParse name;
+ TInt err = Backend()->ResolvePath(name,_path,NULL);
+ if (!err)
+ err = Open(name.DriveAndPath());
+ if (err)
+ MapError(err,*aErrno);
+ return err;
+ }
+
+TInt __EPOC32_WDIR::Open(const TDesC& aPath)
+ {
+ delete iPath;
+ iPath=aPath.Alloc(); //allocate space for a hbufc and initialise it to the TDesC contents
+ return Open();
+ }
+
+TInt __EPOC32_WDIR::Open()
+ {
+ delete iEntries;
+ iEntries=0;
+ iIndex = 0;
+ iCount = 0 ;
+ if (iPath==0)
+ {
+ return ENOMEM;
+ }
+
+ RFs& session = Backend()->FileSession();
+ TInt err=session.GetDir(*iPath,KEntryAttMaskSupported,ESortByName+EDescending,iEntries);
+
+ if (!err)
+ {
+ // iCount is actually a Last Index, not the number of entries!
+ iCount = iEntries->Count()-1;
+ iIndex = 0;
+ }
+ return err;
+ }
+
+extern "C" {
+
+/* A reentrant version of open() */
+EXPORT_C int _open_r (int *aErrno, const wchar_t *name, int mode, int perms)
+ {
+ return Backend()->open(name, mode, perms, *aErrno);
+ }
+
+/*A reentrant version of wopen() */
+EXPORT_C int _wopen_r (int *aErrno, const wchar_t *name, int mode, int perms)
+ {
+ return Backend()->open(name, mode, perms, *aErrno);
+ }
+
+/* A reentrant version of read()*/
+EXPORT_C int _read_r (int *aErrno, int fd, char *buf, size_t nbyte)
+ {
+ return Backend()->read(fd, buf, nbyte, *aErrno);
+ }
+
+
+/* A reentrant version of write()*/
+EXPORT_C int _write_r (int *aErrno, int fd, const char *buf, size_t nbyte)
+ {
+ return Backend()->write(fd, buf, nbyte, *aErrno);
+ }
+
+
+/* A reentrant version of close()*/
+EXPORT_C int _close_r (int *aErrno, int fd)
+ {
+ return Backend()->close(fd, *aErrno);
+ }
+
+/* A reentrant version of fsync()*/
+EXPORT_C int _fsync_r (int *aErrno, int fd)
+ {
+ return Backend()->fsync(fd, *aErrno);
+ }
+
+/*A reentrant version of fseek()*/
+EXPORT_C off_t _lseek_r (int *aErrno, int fd, off_t pos, int whence)
+ {
+ return Backend()->lseek(fd, pos, whence, *aErrno);
+ }
+
+
+/* A reentrant version of fstat()*/
+EXPORT_C int _fstat_r (int *aErrno, int fd, struct stat *st)
+ {
+ return Backend()->fstat(fd, st, *aErrno);
+ }
+
+/* A reentrant version of stat().
+*/
+EXPORT_C int _stat_r (int *aErrno, const wchar_t *name, struct stat *st)
+ {
+ return Backend()->stat(name, st, *aErrno);
+ }
+
+/* A reentrant version of lstat().
+*/
+EXPORT_C int _lstat_r (int *aErrno, const wchar_t *name, struct stat *st)
+ {
+ return Backend()->lstat(name, st, *aErrno);
+ }
+
+EXPORT_C int _utime_r (int *aErrno, const wchar_t *name,const struct utimbuf *filetimes)
+ {
+ return Backend()->utime(name, filetimes, *aErrno);
+ }
+
+
+/* A reentrant version of wstat().
+*/
+EXPORT_C int _wstat_r (int *aErrno, const wchar_t *name, struct stat *st)
+ {
+ return Backend()->stat(name, st, *aErrno);
+ }
+
+/* A reentrant version of dup().
+*/
+EXPORT_C int _dup_r (int *aErrno, int aFid)
+ {
+ return Backend()->dup(aFid, *aErrno);
+ }
+
+/* A reentrant version of dup2().
+*/
+EXPORT_C int _dup2_r (int *aErrno, int aFid1, int aFid2)
+ {
+ return Backend()->dup2(aFid1, aFid2, *aErrno);
+ }
+
+/* A reentrant version of ioctl().
+*/
+EXPORT_C int _ioctl_r (int *aErrno, int aFid, int aCmd, void* aParam)
+ {
+ return Backend()->ioctl(aFid, aCmd, aParam, *aErrno);
+ }
+
+/* A wide-character version of reentrant of getcwd().
+*/
+EXPORT_C wchar_t * _wgetcwd_r (int *aErrno, wchar_t *_buf, size_t _size)
+ {
+ if (_buf==0)
+ {
+ _buf=(wchar_t *)User::Alloc(_size*sizeof(wchar_t));
+ if (_buf==0)
+ {
+ *aErrno=ENOMEM;
+ return _buf;
+ }
+ }
+ return Backend()->getcwd(_buf, _size, *aErrno);
+ }
+
+/* A reentrant version of chdir().
+*/
+EXPORT_C int _chdir_r (int *aErrno, const wchar_t *_path)
+ {
+ return Backend()->chdir(_path, *aErrno);
+ }
+
+/* A reentrant version of wchdir().
+*/
+EXPORT_C int _wchdir_r (int *aErrno, const wchar_t *_path)
+ {
+ return Backend()->chdir(_path, *aErrno);
+ }
+
+/* A reentrant version of rmdir().
+*/
+EXPORT_C int _rmdir_r (int *aErrno, const wchar_t *_path)
+ {
+ return Backend()->rmdir(_path, *aErrno);
+ }
+
+
+/* A reentrant version of wrmdir().
+*/
+EXPORT_C int _wrmdir_r (int *aErrno, const wchar_t *_path)
+ {
+ return Backend()->rmdir(_path, *aErrno);
+ }
+
+
+/* A reentrant version of mkdir().
+*/
+EXPORT_C int _mkdir_r (int *aErrno, const wchar_t *_path, mode_t _mode)
+ {
+ return Backend()->mkdir(_path, _mode, *aErrno);
+ }
+
+/* A reentrant version of wmkdir().
+*/
+EXPORT_C int _wmkdir_r (int *aErrno, const wchar_t *_path, mode_t _mode)
+ {
+ return Backend()->mkdir(_path, _mode, *aErrno);
+ }
+
+
+/* A reentrant version of chmod().
+*/
+EXPORT_C int _chmod_r (int *aErrno, const wchar_t *_path, mode_t _mode)
+ {
+ return Backend()->chmod(_path, _mode, *aErrno);
+ }
+
+/* A reentrant version of chmod().
+*/
+EXPORT_C int _fchmod_r (int *aErrno, int _fd , mode_t _mode)
+ {
+ return Backend()->fchmod(_fd, _mode, *aErrno);
+ }
+/* A reentrant version of wchmod().
+*/
+EXPORT_C int _wchmod_r (int *aErrno, const wchar_t *_path, mode_t _mode)
+ {
+ return Backend()->chmod(_path, _mode, *aErrno);
+ }
+
+/* A wide-character version of reentrant of unlink().
+*/
+EXPORT_C int _wunlink_r (int *aErrno, const wchar_t *_path)
+ {
+ return Backend()->unlink(_path, *aErrno);
+ }
+
+
+/* A reentrant version of rename().
+*/
+EXPORT_C int _rename_r (int *aErrno, const wchar_t *oldpath, const wchar_t *newpath)
+ {
+ return Backend()->rename(oldpath, newpath, *aErrno);
+ }
+
+
+/* A wide-character version of reentrant of rename().
+*/
+EXPORT_C int _wrename_r (int *aErrno, const wchar_t *oldpath, const wchar_t *newpath)
+ {
+ return Backend()->rename(oldpath, newpath, *aErrno);
+ }
+
+/* A wide-character version of reentrant of realpath().
+*/
+EXPORT_C wchar_t * _wrealpath_r (int *aErrno, const wchar_t *relpath, wchar_t *resolved)
+ {
+ if(relpath == NULL || resolved == NULL) //invalid arguments
+ {
+ *aErrno = EFAULT;
+ return (NULL);
+ }
+ TPtr16 name((TText16*)resolved,MAXPATHLEN);
+ TParse path;
+ TInt err = Backend()->ResolvePath(path, relpath, &name);
+ if (!err)
+ {
+ err = path.SetNoWild(path.DriveAndPath(),NULL,&name);
+ if (!err)
+ {
+ name = path.FullName();
+ name.ZeroTerminate();
+ return resolved;
+ }
+ }
+ MapError(err, *aErrno);
+ return 0;
+ }
+
+LOCAL_C TInt _parseCmd (const wchar_t* command, wchar_t* exepath, TDes& buf)
+ {
+ TLex lexer((TText*)command);
+ buf = lexer.NextToken();
+ WcsCpy(exepath,(wchar_t*)buf.PtrZ());
+
+ lexer.SkipSpace();
+ if (!lexer.Eos())
+ {
+ buf = lexer.Remainder();
+ buf.TrimRight();
+ }
+ return KErrNone;
+ }
+
+EXPORT_C int _wpopen_r (int* aErrno, const wchar_t* command, const char* mode)
+ {
+ wchar_t exepath[KMaxPath+1];
+ TFileName buf;
+
+ if (_parseCmd(command, exepath, buf) == KErrNotFound)
+ {
+ // no such file
+ *aErrno = ENOENT;
+ return -1;
+ }
+
+ return Backend()->popen(exepath, (wchar_t*)buf.PtrZ(), mode, *aErrno);
+ }
+
+EXPORT_C int _pclose_r(int* aErrno, int aFid)
+ {
+ return Backend()->pclose(aFid, *aErrno);
+ }
+
+/* A wide-character version of reentrant of popen3().
+*/
+EXPORT_C int _wpopen3_r (int* aErrno, const wchar_t* file, const wchar_t* cmd,
+ wchar_t** envp, int fids[3])
+ {
+
+ wchar_t* cmdargs = NULL;
+ if (cmd)
+ {
+ TFileName buf = (TText*)cmd;
+ buf.Trim();
+ cmdargs = (wchar_t*)buf.PtrZ();
+ }
+
+ return Backend()->popen3(file, cmdargs, envp, fids, *aErrno);
+ }
+
+
+/* A reentrant version of waitpid().
+*/
+EXPORT_C int _waitpid_r (int *aErrno, int pid, int* status, int options)
+ {
+ return Backend()->waitpid(pid, status, options, *aErrno);
+ }
+
+
+/* A reentrant version of wait().
+*/
+EXPORT_C int _wait_r (int *aErrno, int* status)
+ {
+ return _waitpid_r(aErrno, -1, status, 0);
+ }
+
+
+/* A wide-character version of reentrant of system().
+*/
+EXPORT_C int _wsystem_r (int *aErrno, const wchar_t* command)
+ {
+ wchar_t exepath[KMaxPath+1];
+ TFileName buf;
+
+ if (NULL == command)
+ {
+ return 1; // special case, says that we do support wsystem().
+ }
+
+ if (_parseCmd(command, (wchar_t*)exepath, buf) == KErrNotFound)
+ {
+ // no such file
+ *aErrno = ENOENT;
+ return -1;
+ }
+
+ return Backend()->system(exepath, (wchar_t*)buf.PtrZ(), *aErrno);
+ }
+
+
+/* A reentrant version of select().
+*/
+EXPORT_C int _select_r(int *aErrno, int maxfd, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *tvptr)
+ {
+ return Backend()->select(maxfd, readfds, writefds, exceptfds, tvptr, *aErrno);
+ }
+
+
+EXPORT_C int _fchdir_r(int *aErrno, int filedesc)
+ {
+ struct stat st;
+
+ if(_fstat_r(aErrno, filedesc, &st)!=0)
+ {
+ *aErrno = EBADF ;//Not an open file descriptor
+ return -1;
+ }
+ else
+ {
+ if (!(S_ISDIR(st.st_mode)))
+ {
+ *aErrno = ENOTDIR ; //Not a directory
+ return -1;
+ }
+ }
+
+ const wchar_t* dirName(NULL) ;
+ dirName = Backend()->GetDirName (filedesc);
+
+ if( dirName )
+ {
+ return Backend()->chdir(dirName, *aErrno);
+ }
+ else
+ {
+ //fildesc does not refer to a valid fd.
+ *aErrno = ENOTDIR;
+ return -1;
+ }
+ }
+
+
+/*
+Gets the path name of the current working directory.
+If a buffer is specified, the path name is placed in that buffer,
+and the address of the buffer is returned.
+@return If successful returns buf, if a non-null pointer was specified,
+or the address of the allocated memory otherwise.
+@param anErrno Ref to the error no.
+@param _buf Points to the buffer to copy the current working directory to,
+or NULL if getcwd() should allocate the buffer.
+@param _size Is the size, in bytes, of the array of characters that buf points to.
+*/
+/* A reentrant version of getcwd()*/
+EXPORT_C wchar_t * _getcwd_r (int *aErrno, wchar_t *_buf, size_t _size)
+ {
+ return Backend()->getcwd(_buf, _size, *aErrno);
+ }
+
+// -----------------------------------------------------------------------------
+// Function name: link
+// Description: Provides link functionality.
+// Returns: 0 : On success
+// -1 : On error
+// In case of error, errno value set
+// Remark: This is a simulated functionality and not supported by the platform
+// -----------------------------------------------------------------------------
+//
+
+EXPORT_C int _link_r(int *aErrno, const wchar_t *_oldwidename, const wchar_t *_newwidename)
+ {
+ return Backend()->link(_oldwidename, _newwidename, *aErrno);
+ }
+
+
+// -----------------------------------------------------------------------------
+// Function name: unlink
+// Description: Provides unlink functionality.
+// Returns: 0 : On success
+// -1 : On error
+// In case of error, errno value set
+//
+// -----------------------------------------------------------------------------
+//
+
+EXPORT_C int _unlink_r(int *aErrno, const wchar_t *_pathwidename)
+ {
+ return Backend()->unlink(_pathwidename, *aErrno);
+ }
+
+
+EXPORT_C int _posix_spawn_r(pid_t* 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 Backend()->posix_spawn(pid, wpath, file_actions, attrp, wargs, wenvp);
+ }
+
+// -----------------------------------------------------------------------------
+// Function name: exit
+// Description: Provides exit functionality.
+// In case of error, errno value set
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void _exit_r(int code)
+ {
+ return Backend()->Exit(code);
+ }
+
+// -----------------------------------------------------------------------------
+// _fcntl_r() : A reentrant version of fcntl().
+// This API is used for setting a file descriptor as non-blocking
+// Returns: System wide error code
+// -----------------------------------------------------------------------------
+//
+EXPORT_C int _fcntl_r (int *aErrno, int aFid, int aCmd, long anArg)
+ {
+ return Backend()->fcntl(aFid, aCmd, anArg, *aErrno);
+ }
+
+//
+EXPORT_C DIR* _opendir_r (int* aErrno, const wchar_t* _path)
+ {
+ __EPOC32_DIR* dp = new __EPOC32_DIR();
+ if (!dp ||(Backend()->AddToDirList((DIR*)dp) != KErrNone))
+ {
+ *aErrno = ENOENT;
+ return 0;
+ }
+ TInt err = dp->Open(_path,aErrno);
+ if (err)
+ {
+ Backend()->RemoveDirFromList((DIR*)dp);
+ delete dp;
+ return 0;
+ }
+
+ return (DIR *)dp;
+ }
+
+//
+EXPORT_C int _wclosedir_r(int* aErrno, WDIR* dp)
+ {
+ if(Backend()->RemoveDirFromList((DIR*)dp) == KErrNotFound)
+ {
+ *aErrno = EBADF;
+ }
+ delete dp;
+ return 0;
+ }
+
+//
+
+EXPORT_C struct dirent* _readdir_r (int* aErrno, DIR *dp)
+ {
+ __EPOC32_DIR *Dp = (__EPOC32_DIR *)dp ;
+
+ if(!dp || Backend()->FindInDirList((DIR*)dp) == KErrNotFound )
+ {
+ *aErrno = EBADF;
+ return 0;
+ }
+ if (_wreaddir_r(Dp))
+ {
+ if (Dp->UpdateNarrow()>=0)
+ {
+ return &Dp->iCurrentNarrow;
+ }
+ else
+ {
+ *aErrno = EINVAL;
+ }
+ }
+ return 0;
+ }
+
+EXPORT_C struct wdirent* _wreaddir_r(WDIR *dp)
+ {
+ struct wdirent *ep=&dp->iCurrent;
+ if ((dp->iIndex < 0) || (dp->iIndex > dp->iCount ))
+ return (wdirent *) NULL;
+
+ const TEntry& entry=(*dp->iEntries)[(dp->iIndex)++];
+ // in practice, these files must have been created as "X:\something", so they
+ // can't really be longer than KMaxFileName-3
+ dp->iCurrentName.Copy(entry.iName);
+ dp->iCurrentName.ZeroTerminate();
+ ep->d_namlen=(short)dp->iCurrentName.Length();
+ ep->d_name=(wchar_t*)dp->iCurrentName.PtrZ();
+ return ep;
+ }
+
+EXPORT_C void _wrewinddir_r(WDIR *dp)
+ {
+ if (dp==0)
+ return;
+ (void) dp->Open(); // POSIX doesn't allow for rewind failing
+ }
+
+// -----------------------------------------------------------------------------
+//int _setecho_r(int *aErrno, int aFd, size_t aEchoVal)
+//
+//Sets the echo flag for this fd.
+// -----------------------------------------------------------------------------
+
+EXPORT_C int _setecho_r(int *aErrno, int aFd, uint8_t aEchoVal)
+ {
+ return Backend()->SetEcho(aFd, aEchoVal, *aErrno);
+ }
+
+} //extern "C" end
+
+// These functions should be out of extern "C"
+/* A reentrant version of aselect().
+*/
+EXPORT_C int _aselect_r(int *aErrno, int maxfd, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *tvptr,
+ TRequestStatus* requeststatus)
+ {
+ return Backend()->aselect(maxfd, readfds, writefds, exceptfds, tvptr,requeststatus, *aErrno);
+ }
+
+/* A reentrant version of cancelaselect().
+*/
+EXPORT_C int _cancelaselect_r(int *aErrno, TRequestStatus* requeststatus)
+ {
+ return Backend()->cancelaselect(requeststatus, *aErrno);
+ }
+
+/* A reentrant version of eselect().
+*/
+EXPORT_C int _eselect_r(int *aErrno, int maxfd, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *tvptr, int numreqs,
+ TRequestStatus* waitarray)
+ {
+ return Backend()->eselect(maxfd, readfds, writefds, exceptfds, tvptr,numreqs, waitarray,*aErrno);
+ }
+