diff -r 000000000000 -r bde4ae8d615e os/ossrv/genericopenlibs/cstdlib/LPOSIX/POSIX.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/ossrv/genericopenlibs/cstdlib/LPOSIX/POSIX.CPP Fri Jun 15 03:10:57 2012 +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 +#include +#include "LPOSIX.H" +#include +#include + +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=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 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 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"