--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/cstdlib/LPOSIX/POSIX.CPP Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,509 @@
+// Copyright (c) 1998-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:
+// POSIX systems calls implemented over EPOC32
+//
+//
+
+#include "SYSIF.H"
+#include <unistd.h>
+#include <errno.h>
+#include "LPOSIX.H"
+#include <utf.h>
+#include <networking/dnd_err.h>
+
+GLDEF_C TInt GetFullPath(TParse& aParse, const TText16* upath, RFs& aSession, TDes* aFileName)
+//
+// Parse a path of the form "[C:][\]AAA\..\.\BBB\xxx" where:
+// . indicates the current directory
+// .. indicates move to the parent directory
+// An optional "\" at the start of the path indicates the path is not relative to the current path,
+// and is implied if the drive specifier is present
+// If aFileName is non-NULL then the final component is a filename and should be copied into
+// the aFileName descriptor.
+//
+ {
+
+ TInt r;
+ TBuf<3> drive;
+ TFileName nextBit;
+ TText16 c=*upath;
+
+ if (c && upath[1]==KDriveDelimiter)
+ {
+ // drive name specified
+ if (c==L'?')
+ drive.Zero(); // use "?:" to mean scan across drives
+ else
+ {
+ drive.Copy(TPtrC16(upath, 2));
+ drive.UpperCase();
+ }
+ upath+=2;
+ drive.Append(TChar(KPathDelimiter)); // enforce absoluteness
+ }
+ else
+ {
+ // no leading drive specifier
+ drive.Zero();
+ if (c==KPathDelimiter||c==L'/')
+ {
+ upath+=1;
+ drive.Append(TChar(KPathDelimiter));
+ }
+ }
+ r = aSession.Parse(drive, aParse);
+
+ // upath now looks like a relative pathname, to be added onto
+ // aParse a directory at a time. Note that '/' is not allowed in
+ // EPOC32 file or directory names, so treat it as an alternative separator
+
+ c=*upath;
+ while (c && (r==KErrNone))
+ {
+ const TText16* ustart=upath;
+ do
+ c=*upath++;
+ while (c && c!=KPathDelimiter && c!=L'/');
+
+ TInt len=(upath-ustart)-1; // excludes delimiter
+ if (len==0)
+ continue;
+ if (ustart[0]==L'.')
+ {
+ if (len==1)
+ continue; // directory . ignored
+ if (len==2 && ustart[1]==L'.')
+ {
+ // directory ..
+ (void) aParse.PopDir(); // just stick at root dir, no errors
+ continue;
+ }
+ }
+ if (len>=KMaxFileName)
+ return ENAMETOOLONG;
+ if (c==L'\0' && aFileName!=NULL)
+ {
+ // it's the trailing filename
+ aFileName->Copy(TPtrC16(ustart, len));
+ break;
+ }
+ else
+ {
+ // it's a component of the accumulating path
+ nextBit.Copy(TPtrC16(ustart, len));
+ r = aParse.AddDir(nextBit);
+ }
+ }
+ return(r);
+ }
+
+
+GLDEF_C TInt GetFullFile(TFileName& aName, const TText16* upath, RFs& aSession)
+// Use GetFullPath to establish the pathname, then add the filename onto the end
+ {
+ TParse path;
+ TInt err = GetFullPath(path,upath,aSession,&aName);
+ if (err!=KErrNone)
+ return err;
+ // Wildcard drive letter for searching across drives
+ if (upath[0]==L'?' && upath[1]==L':')
+ {
+ TFindFile search(aSession);
+ err=search.FindByDir(aName,path.Path());
+ if (!err)
+ {
+ aName=search.File();
+ return KErrNone;
+ }
+ }
+ err = path.SetNoWild(path.DriveAndPath(),NULL,&aName);
+ if (!err)
+ aName = path.FullName();
+ return err;
+ }
+
+
+// Set errno from an E32STD.H error code or a STDLIB errno value
+
+static const TUint8 EPOCtoERRNO[43] = {
+ ENOENT, // KErrNotFound=(-1);
+ 0, // KErrGeneral=(-2);
+ EINTR, // KErrCancel=(-3);
+ ENOMEM, // KErrNoMemory=(-4);
+ ENOSYS, // KErrNotSupported=(-5);
+ EINVAL, // KErrArgument=(-6);
+ 0, // KErrTotalLossOfPrecision=(-7);
+ 0, // KErrBadHandle=(-8);
+ ERANGE, // KErrOverflow=(-9);
+ ERANGE, // KErrUnderflow=(-10);
+ EEXIST, // KErrAlreadyExists=(-11);
+ ENOENT, // KErrPathNotFound=(-12);
+ EPIPE, // KErrDied=(-13);
+ EACCES, // KErrInUse=(-14);
+ EPIPE, // KErrServerTerminated=(-15);
+ EBUSY, // KErrServerBusy=(-16);
+ 0, // KErrCompletion=(-17);
+ 0, // KErrNotReady=(-18);
+ 0, // KErrUnknown=(-19);
+ 0, // KErrCorrupt=(-20);
+ EACCES, // KErrAccessDenied=(-21);
+ EACCES, // KErrLocked=(-22);
+ 0, // KErrWrite=(-23);
+ ENODEV, // KErrDisMounted=(-24);
+ EPIPE, // KErrEof=(-25);
+ ENOSPC, // KErrDiskFull=(-26);
+ 0, // KErrBadDriver=(-27);
+ EINVAL, // KErrBadName=(-28);
+ ECOMM, // KErrCommsLineFail=(-29);
+ ECOMM, // KErrCommsFrame=(-30);
+ ECOMM, // KErrCommsOverrun=(-31);
+ ECOMM, // KErrCommsParity=(-32);
+ ETIMEDOUT, // KErrTimedOut=(-33);
+ ECONNREFUSED, // KErrCouldNotConnect=(-34);
+ 0, // KErrCouldNotDisconnect=(-35);
+ EPIPE, // KErrDisconnected=(-36);
+ 0, // KErrBadLibraryEntryPoint=(-37);
+ 0, // KErrBadDescriptor=(-38);
+ 0, // KErrAbort=(-39);
+ 0, // KErrTooBig=(-40);
+ EDOM, // KErrDivideByZero=(-41);
+ EDOM, // KErrBadPower=(-42);
+ ENOSPC // KErrDirFull=(-43);
+ };
+
+
+EXPORT_C int MapError(TInt err, int& anErrno)
+ {
+ if (err==0)
+ return err; // i.e. return 0 without changing errno
+ TInt ret=err;
+ if (err<KErrNone && err>=KErrDirFull)
+ {
+ ret=EPOCtoERRNO[-1-err];
+ if (ret==0)
+ ret=err; // no sensible translation
+ }
+ else if ((err == KErrDndNameNotFound) || (err == KErrDndAddrNotFound))
+ // KErrDndNameNotFound Returned when no data found for GetByName
+ // KErrDndAddrNotFound Returned when no data found for GetByAddr
+ {
+ ret=ENOENT;
+ }
+ anErrno=ret; // KErr* values are negative, so will be distinct anyway
+ return -1;
+ }
+
+
+
+// Directory enumeration
+
+NONSHARABLE_STRUCT(__EPOC32_WDIR) : public CBase // aka "class __EPOC32_WDIR with everything public"
+ {
+public:
+ __EPOC32_WDIR(struct _reent* aContext) : iContext(aContext) {}
+ ~__EPOC32_WDIR();
+
+ TInt Open();
+ TInt Open(const TDesC& aPath);
+ TInt Open(const wchar_t *_path);
+
+ virtual TInt UpdateNarrow();
+ struct _reent *iContext;
+ HBufC* iPath;
+ CDir* iEntries;
+ TInt iIndex; // counting down, 0 means "finished"
+ struct wdirent iCurrent;
+ TBuf16<KMaxFileName> iCurrentName;
+ };
+
+TInt __EPOC32_WDIR::UpdateNarrow()
+{
+ return -1; //this is not supported.
+}
+
+
+NONSHARABLE_STRUCT(__EPOC32_DIR) : public __EPOC32_WDIR
+ {
+public:
+ __EPOC32_DIR(struct _reent* aContext) : __EPOC32_WDIR(aContext) {}
+ ~__EPOC32_DIR() {}
+
+ virtual TInt UpdateNarrow();
+ struct dirent iCurrentNarrow;
+ TBuf8<KMaxFileName> iCurrentNarrowName;
+ };
+
+
+TInt __EPOC32_DIR::UpdateNarrow()
+{
+ //update the narrow one
+
+ TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(iCurrentNarrowName, iCurrentName);
+ if (ret >= 0)
+ {
+ iCurrentNarrow.d_namlen=(short)iCurrentNarrowName.Length();
+ iCurrentNarrow.d_name = (char*)iCurrentNarrowName.PtrZ();
+ }
+ return ret;
+}
+
+
+__EPOC32_WDIR::~__EPOC32_WDIR()
+ {
+ delete iPath;
+ delete iEntries;
+ }
+
+TInt __EPOC32_WDIR::Open(const wchar_t *_path)
+ {
+ MSystemInterface& sysIf=Interface(iContext);
+ TParse name;
+ TInt err = sysIf.ResolvePath(name,_path,NULL);
+ if (!err)
+ err = Open(name.DriveAndPath());
+ if (err)
+ MapError(err,iContext->_errno);
+ 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=-1;
+ if (iPath==0)
+ return ENOMEM;
+ RFs session;
+ TInt err=session.Connect();
+ if (err)
+ return err;
+ err=session.GetDir(*iPath,KEntryAttMaskSupported,ESortByName+EDescending,iEntries);
+ session.Close();
+ if (!err)
+ iIndex=iEntries->Count();
+ return err;
+ }
+
+extern "C" {
+
+/**
+Resets the position to the beginning of the directory.
+@param dp directory
+*/
+EXPORT_C void wrewinddir (WDIR *dp)
+ {
+ if (dp==0)
+ return;
+ (void) dp->Open(); // POSIX doesn't allow for rewind failing
+ }
+
+/**
+Closes the directory.
+@param dp directory to close.
+*/
+EXPORT_C int wclosedir (WDIR *dp)
+ {
+ delete dp;
+ return 0;
+ }
+
+/**
+Opens a directory.
+@return a pointer to the dir object.
+This object describes the directory
+and is used in subsequent operations on the directory
+If error, returns NULL.
+@param _path path to the directory to be opened.
+*/
+EXPORT_C DIR *opendir (const char *_path)
+ {
+ return _opendir_r(_REENT,_path);
+ }
+
+/** A wide-character version of opendir()
+*/
+EXPORT_C WDIR *wopendir (const wchar_t *_path)
+ {
+ return _wopendir_r(_REENT,_path);
+ }
+
+/** A reentrant version of opendir().
+*/
+EXPORT_C DIR *_opendir_r (struct _reent *r, const char *_path)
+ {
+
+ wchar_t _widepath[KMaxFileName+1];
+
+ if (mbstowcs(_widepath, _path, KMaxFileName) < 0)
+ {
+ MapError(EILSEQ,r->_errno);
+ return 0;
+ }
+ //coverity[alloc_fn]
+ //coverity[assign]
+
+ DIR* dp = new __EPOC32_DIR(r);
+ if (dp==0)
+ {
+ r->_errno=ENOMEM;
+ return 0;
+ }
+
+ //coverity[leave_without_push]
+
+ TInt err = dp->Open(_widepath);
+ if (err)
+ {
+ delete dp;
+ return 0;
+ }
+ return dp;
+ }
+
+/** A reentrant version of wopendir().
+*/
+EXPORT_C WDIR *_wopendir_r (struct _reent *r, const wchar_t *_path)
+ {
+
+ //coverity[alloc_fn]
+ //coverity[assign]
+
+ WDIR* dp = new __EPOC32_WDIR(r);
+ if (dp==0)
+ {
+ r->_errno=ENOMEM;
+ return 0;
+ }
+ //coverity[leave_without_push]
+
+ TInt err = dp->Open(_path);
+ if (err)
+ {
+ delete dp;
+ return 0;
+ }
+ return dp;
+ }
+
+/**
+Sets the index position of the directory stream specified by dp
+to the position specified by index.
+*/
+EXPORT_C void wseekdir(WDIR *dp,off_t index)
+ {
+ dp->iIndex=index;
+ }
+
+EXPORT_C off_t wtelldir(const WDIR *dp)
+ {
+ return dp->iIndex;
+ }
+
+EXPORT_C struct wdirent *wreaddir (WDIR *dp)
+ {
+ if (dp->iIndex<=0)
+ return 0;
+ struct wdirent *ep=&dp->iCurrent;
+ 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;
+ }
+
+/**
+Returns a pointer to a dirent structure representing
+the next directory entry in the directory stream pointed to be dir.
+It returns NULL on reaching the end-of-file or if an error occurred.
+@return a pointer to a dirent structure, or NULL if an error occurs
+or end-of-file is reached.
+@param dp Points to the directory stream of the directory.
+*/
+EXPORT_C struct dirent *readdir (DIR *dp)
+ {
+ return _readdir_r(_REENT, dp);
+ }
+
+/** A reentrant version of readdir().
+*/
+EXPORT_C struct dirent *_readdir_r (struct _reent *r, DIR *dp)
+ {
+ if (wreaddir(dp))
+ {
+ if (dp->UpdateNarrow()>=0)
+ return &dp->iCurrentNarrow;
+ else
+ r->_errno = EINVAL;
+ }
+
+ return 0;
+ }
+
+/**
+Sets the position (associated with the directory stream that dirp points to)
+to the beginning of the directory.
+Additionally, it causes the directory stream to refer to the current state of
+the corresponding directory.
+@param dp Points to the directory stream of the directory to rewind.
+*/
+EXPORT_C void rewinddir (DIR *dp)
+ {
+ wrewinddir(dp);
+ }
+
+/**
+closes the directory stream that dirp refers to.
+The memory associated with the directory stream is released.
+When this function returns, the value of dirp no longer point to
+an accessible object of type DIR
+@return a value of zero. On failure, it returns -1
+@param dp Is the directory pointer to close (from opendir()).
+*/
+EXPORT_C int closedir (DIR *dp)
+ {
+ return wclosedir(dp);
+ }
+
+/**
+sets the position of the next readdir() operation on the directory
+stream specified by dp to the position specified by index
+@param dp Points to the directory stream of the directory
+@param index
+*/
+EXPORT_C void seekdir(DIR *dp,off_t index)
+ {
+ wseekdir(dp,index);
+ }
+
+/**
+Returns the current location associated with the directory stream dir.
+@return the current location in the directory stream or -1 if an error occurs.
+@param dp Points to the directory stream of the directory
+*/
+EXPORT_C off_t telldir(const DIR *dp)
+ {
+ return wtelldir(dp);
+ }
+
+} // extern "C"