genericopenlibs/cstdlib/LPOSIX/POSIX.CPP
changeset 0 e4d67989cc36
--- /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"