os/ossrv/genericopenlibs/cstdlib/LPOSIX/POSIX.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // POSIX systems calls implemented over EPOC32
    15 // 
    16 //
    17 
    18 #include "SYSIF.H"
    19 #include <unistd.h>
    20 #include <errno.h>
    21 #include "LPOSIX.H"
    22 #include <utf.h>
    23 #include <networking/dnd_err.h>
    24 
    25 GLDEF_C TInt GetFullPath(TParse& aParse, const TText16* upath, RFs& aSession, TDes* aFileName)
    26 //
    27 // Parse a path of the form "[C:][\]AAA\..\.\BBB\xxx" where:
    28 // .  indicates the current directory
    29 // .. indicates move to the parent directory
    30 // An optional "\" at the start of the path indicates the path is not relative to the current path,
    31 // and is implied if the drive specifier is present
    32 // If aFileName is non-NULL then the final component is a filename and should be copied into 
    33 // the aFileName descriptor.
    34 //
    35 	{
    36 
    37 	TInt r;
    38 	TBuf<3> drive;
    39 	TFileName nextBit;
    40 	TText16 c=*upath;
    41 
    42 	if (c && upath[1]==KDriveDelimiter) 
    43 		{
    44 		// drive name specified
    45 		if (c==L'?')
    46 			drive.Zero();			// use "?:" to mean scan across drives
    47 		else
    48 			{
    49 			drive.Copy(TPtrC16(upath, 2));
    50 			drive.UpperCase();
    51 			}
    52 		upath+=2;
    53 		drive.Append(TChar(KPathDelimiter));	// enforce absoluteness
    54 		}
    55 	else
    56 		{
    57 		// no leading drive specifier
    58 		drive.Zero();
    59 		if (c==KPathDelimiter||c==L'/')
    60 			{
    61 			upath+=1;
    62 			drive.Append(TChar(KPathDelimiter));
    63 			}
    64 		}
    65 	r = aSession.Parse(drive, aParse);
    66 
    67 	// upath now looks like a relative pathname, to be added onto
    68 	// aParse a directory at a time. Note that '/' is not allowed in
    69 	// EPOC32 file or directory names, so treat it as an alternative separator
    70 
    71 	c=*upath;
    72 	while (c && (r==KErrNone))
    73 		{
    74 		const TText16* ustart=upath;
    75 		do 
    76 			c=*upath++;
    77 		while (c && c!=KPathDelimiter && c!=L'/');
    78 
    79 		TInt len=(upath-ustart)-1;		// excludes delimiter
    80 		if (len==0)
    81 			continue;
    82 		if (ustart[0]==L'.')
    83 			{
    84 			if (len==1)
    85 				continue;	// directory . ignored
    86 			if (len==2 && ustart[1]==L'.')
    87 				{
    88 				// directory ..
    89 				(void) aParse.PopDir();	// just stick at root dir, no errors
    90 				continue;
    91 				}
    92 			}
    93 		if (len>=KMaxFileName)
    94 			return ENAMETOOLONG;
    95 		if (c==L'\0' && aFileName!=NULL)
    96 			{
    97 			// it's the trailing filename
    98 			aFileName->Copy(TPtrC16(ustart, len));
    99 			break;
   100 			}
   101 		else	
   102 			{
   103 			// it's a component of the accumulating path
   104 			nextBit.Copy(TPtrC16(ustart, len));
   105 			r = aParse.AddDir(nextBit);
   106 			}
   107 		}
   108 	return(r);
   109 	}
   110 
   111 
   112 GLDEF_C TInt GetFullFile(TFileName& aName, const TText16* upath, RFs& aSession)
   113 // Use GetFullPath to establish the pathname, then add the filename onto the end
   114 	{
   115 	TParse path;
   116 	TInt err = GetFullPath(path,upath,aSession,&aName);
   117 	if (err!=KErrNone)
   118 		return err;
   119 	// Wildcard drive letter for searching across drives
   120 	if (upath[0]==L'?' && upath[1]==L':')
   121 		{
   122 		TFindFile search(aSession);
   123 		err=search.FindByDir(aName,path.Path());
   124 		if (!err)
   125 			{
   126 			aName=search.File();
   127 			return KErrNone;
   128 			}
   129 		}
   130 	err = path.SetNoWild(path.DriveAndPath(),NULL,&aName);
   131 	if (!err)
   132 		aName = path.FullName();
   133 	return err;
   134 	}
   135 
   136 
   137 // Set errno from an E32STD.H error code or a STDLIB errno value
   138 
   139 static const TUint8 EPOCtoERRNO[43] = {
   140 	ENOENT,   // KErrNotFound=(-1);
   141 	  0,      // KErrGeneral=(-2);
   142 	EINTR,    // KErrCancel=(-3);
   143 	ENOMEM,   // KErrNoMemory=(-4);
   144 	ENOSYS,   // KErrNotSupported=(-5);
   145 	EINVAL,   // KErrArgument=(-6);
   146 	  0,      // KErrTotalLossOfPrecision=(-7);
   147 	  0,      // KErrBadHandle=(-8);
   148 	ERANGE,   // KErrOverflow=(-9);
   149 	ERANGE,   // KErrUnderflow=(-10);
   150 	EEXIST,   // KErrAlreadyExists=(-11);
   151 	ENOENT,   // KErrPathNotFound=(-12);
   152 	EPIPE,    // KErrDied=(-13);
   153 	EACCES,   // KErrInUse=(-14);
   154 	EPIPE,    // KErrServerTerminated=(-15);
   155 	EBUSY,    // KErrServerBusy=(-16);
   156 	  0,      // KErrCompletion=(-17);
   157 	  0,      // KErrNotReady=(-18);
   158 	  0,      // KErrUnknown=(-19);
   159 	  0,      // KErrCorrupt=(-20);
   160 	EACCES,   // KErrAccessDenied=(-21);
   161 	EACCES,   // KErrLocked=(-22);
   162 	  0,      // KErrWrite=(-23);
   163 	ENODEV,   // KErrDisMounted=(-24);
   164 	EPIPE,    // KErrEof=(-25);
   165 	ENOSPC,   // KErrDiskFull=(-26);
   166 	  0,      // KErrBadDriver=(-27);
   167 	EINVAL,   // KErrBadName=(-28);
   168 	ECOMM,    // KErrCommsLineFail=(-29);
   169 	ECOMM,    // KErrCommsFrame=(-30);
   170 	ECOMM,    // KErrCommsOverrun=(-31);
   171 	ECOMM,    // KErrCommsParity=(-32);
   172     ETIMEDOUT,    // KErrTimedOut=(-33);
   173     ECONNREFUSED, // KErrCouldNotConnect=(-34);
   174 	  0,      // KErrCouldNotDisconnect=(-35);
   175 	EPIPE,    // KErrDisconnected=(-36);
   176 	  0,      // KErrBadLibraryEntryPoint=(-37);
   177 	  0,      // KErrBadDescriptor=(-38);
   178 	  0,      // KErrAbort=(-39);
   179 	  0,      // KErrTooBig=(-40);
   180 	EDOM,     // KErrDivideByZero=(-41);
   181 	EDOM,     // KErrBadPower=(-42);
   182 	ENOSPC    // KErrDirFull=(-43);
   183 	};
   184 
   185 
   186 EXPORT_C int MapError(TInt err, int& anErrno)
   187 	{
   188 	if (err==0)
   189 		return err;	// i.e. return 0 without changing errno
   190 	TInt ret=err;
   191 	if (err<KErrNone && err>=KErrDirFull)
   192 		{
   193 		ret=EPOCtoERRNO[-1-err];
   194 		if (ret==0)
   195 			ret=err;	// no sensible translation
   196 		}
   197 	else if ((err == KErrDndNameNotFound) || (err == KErrDndAddrNotFound))
   198 		// KErrDndNameNotFound Returned when no data found for GetByName
   199 		// KErrDndAddrNotFound Returned when no data found for GetByAddr
   200 		{
   201 		ret=ENOENT;
   202 		}
   203 	anErrno=ret;	// KErr* values are negative, so will be distinct anyway
   204 	return -1;
   205 	}
   206 
   207 
   208 
   209 // Directory enumeration
   210 
   211 NONSHARABLE_STRUCT(__EPOC32_WDIR) : public CBase	// aka "class __EPOC32_WDIR with everything public"
   212 	{
   213 public:
   214 	__EPOC32_WDIR(struct _reent* aContext) : iContext(aContext) {}
   215 	~__EPOC32_WDIR();
   216 
   217 	TInt Open();
   218 	TInt Open(const TDesC& aPath);
   219 	TInt Open(const wchar_t *_path);
   220 
   221 	virtual TInt UpdateNarrow();
   222 	struct _reent *iContext;
   223 	HBufC* iPath;
   224 	CDir* iEntries;
   225 	TInt iIndex;		// counting down, 0 means "finished"
   226 	struct wdirent iCurrent;
   227 	TBuf16<KMaxFileName> iCurrentName;
   228 	};
   229 
   230 TInt __EPOC32_WDIR::UpdateNarrow()
   231 {
   232 	return -1;		//this is not supported.
   233 }
   234 
   235 
   236 NONSHARABLE_STRUCT(__EPOC32_DIR) : public __EPOC32_WDIR
   237 	{
   238 public:
   239 	__EPOC32_DIR(struct _reent* aContext) : __EPOC32_WDIR(aContext) {}
   240 	~__EPOC32_DIR() {}
   241 
   242 	virtual TInt UpdateNarrow();
   243 	struct dirent iCurrentNarrow;
   244 	TBuf8<KMaxFileName> iCurrentNarrowName;
   245 	};
   246 
   247 
   248 TInt __EPOC32_DIR::UpdateNarrow()
   249 {
   250 	//update the narrow one
   251 	
   252 	TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(iCurrentNarrowName, iCurrentName);
   253 	if (ret >= 0)
   254 		{
   255 		iCurrentNarrow.d_namlen=(short)iCurrentNarrowName.Length();
   256 		iCurrentNarrow.d_name = (char*)iCurrentNarrowName.PtrZ();
   257 		}
   258 	return ret;
   259 }
   260 
   261 
   262 __EPOC32_WDIR::~__EPOC32_WDIR()
   263 	{
   264 	delete iPath;
   265 	delete iEntries;
   266 	}
   267 
   268 TInt __EPOC32_WDIR::Open(const wchar_t *_path)
   269 	{
   270 	MSystemInterface& sysIf=Interface(iContext);
   271 	TParse name;
   272 	TInt err = sysIf.ResolvePath(name,_path,NULL);
   273 	if (!err)
   274 		err = Open(name.DriveAndPath());
   275 	if (err)
   276 		MapError(err,iContext->_errno);
   277 	return err;
   278 	}
   279 
   280 TInt __EPOC32_WDIR::Open(const TDesC& aPath)
   281 	{
   282 	delete iPath;
   283 	iPath=aPath.Alloc();		//allocate space for a hbufc and initialise it to the TDesC contents
   284 	return Open();
   285 	}
   286 
   287 TInt __EPOC32_WDIR::Open()
   288 	{
   289 	delete iEntries;
   290 	iEntries=0;
   291 	iIndex=-1;
   292 	if (iPath==0)
   293 		return ENOMEM;
   294 	RFs session;
   295 	TInt err=session.Connect();
   296 	if (err)
   297 		return err;
   298 	err=session.GetDir(*iPath,KEntryAttMaskSupported,ESortByName+EDescending,iEntries);
   299 	session.Close();
   300 	if (!err)
   301 		iIndex=iEntries->Count();
   302 	return err;
   303 	}
   304 
   305 extern "C" {
   306 
   307 /**
   308 Resets the position to the beginning of the directory.
   309 @param dp directory
   310 */
   311 EXPORT_C void wrewinddir (WDIR *dp)
   312 	{
   313 	if (dp==0)
   314 		return;
   315 	(void) dp->Open();	// POSIX doesn't allow for rewind failing
   316 	}
   317 
   318 /**
   319 Closes the directory.
   320 @param dp directory to close.
   321 */
   322 EXPORT_C int wclosedir (WDIR *dp)
   323 	{
   324 	delete dp;
   325 	return 0;
   326 	}
   327 
   328 /**
   329 Opens a directory.
   330 @return a pointer to the dir object.
   331 This object describes the directory 
   332 and is used in subsequent operations on the directory
   333 If error, returns NULL.
   334 @param _path path to the directory to be opened.
   335 */
   336 EXPORT_C DIR *opendir (const char *_path)
   337 	{
   338 	return _opendir_r(_REENT,_path);
   339 	}
   340 
   341 /** A wide-character version of opendir()
   342 */
   343 EXPORT_C WDIR *wopendir (const wchar_t *_path)
   344 	{
   345 	return _wopendir_r(_REENT,_path);
   346 	}
   347 
   348 /** A reentrant version of opendir().
   349 */
   350 EXPORT_C DIR *_opendir_r (struct _reent *r, const char *_path)
   351 	{
   352 	
   353 	wchar_t _widepath[KMaxFileName+1];
   354 	
   355 	if (mbstowcs(_widepath, _path, KMaxFileName) < 0)
   356 		{
   357 		MapError(EILSEQ,r->_errno);
   358 		return 0;
   359 		}
   360 	//coverity[alloc_fn]
   361 	//coverity[assign]
   362 
   363 	DIR* dp = new __EPOC32_DIR(r);
   364 	if (dp==0)
   365 		{
   366 		r->_errno=ENOMEM;
   367 		return 0;
   368 		}
   369 	
   370 	//coverity[leave_without_push]
   371 
   372 	TInt err = dp->Open(_widepath);
   373 	if (err)
   374 		{
   375 		delete dp;
   376 		return 0;
   377 		}
   378 	return dp;
   379 	}
   380 
   381 /** A reentrant version of wopendir().
   382 */
   383 EXPORT_C WDIR *_wopendir_r (struct _reent *r, const wchar_t *_path)
   384 	{
   385 
   386 	//coverity[alloc_fn]
   387 	//coverity[assign]
   388 
   389 	WDIR* dp = new __EPOC32_WDIR(r);
   390 	if (dp==0)
   391 		{
   392 		r->_errno=ENOMEM;
   393 		return 0;
   394 		}
   395 	//coverity[leave_without_push]
   396 
   397 	TInt err = dp->Open(_path);
   398 	if (err)
   399 		{
   400 		delete dp;
   401 		return 0;
   402 		}
   403 	return dp;
   404 	}
   405 
   406 /**
   407 Sets the index position of the directory stream specified by dp 
   408 to the position specified by index.
   409 */
   410 EXPORT_C void wseekdir(WDIR *dp,off_t index)
   411 	{
   412 	dp->iIndex=index;
   413 	}
   414 
   415 EXPORT_C off_t wtelldir(const WDIR *dp)
   416 	{
   417 	return dp->iIndex;
   418 	}
   419 
   420 EXPORT_C struct wdirent *wreaddir (WDIR *dp)
   421 	{
   422 	if (dp->iIndex<=0)
   423 		return 0;
   424 	struct wdirent *ep=&dp->iCurrent;
   425 	const TEntry& entry=(*dp->iEntries)[--(dp->iIndex)];
   426 	// in practice, these files must have been created as "X:\something", so they
   427 	// can't really be longer than KMaxFileName-3
   428 	dp->iCurrentName.Copy(entry.iName);
   429 	dp->iCurrentName.ZeroTerminate();
   430 	ep->d_namlen=(short)dp->iCurrentName.Length();
   431 	ep->d_name=(wchar_t*)dp->iCurrentName.PtrZ();
   432 	return ep;
   433 	}
   434 
   435 /**
   436 Returns  a  pointer  to a dirent structure representing 
   437 the next  directory  entry  in  the directory  stream  pointed  to be dir.
   438 It returns NULL on reaching the end-of-file or if an error occurred.
   439 @return a  pointer  to a dirent structure, or NULL if an error occurs
   440 or  end-of-file  is reached.
   441 @param dp Points to the directory stream of the directory.
   442 */
   443 EXPORT_C struct dirent *readdir (DIR *dp)
   444 	{
   445 	return _readdir_r(_REENT, dp);
   446 	}
   447 
   448 /** A reentrant version of readdir().
   449 */
   450 EXPORT_C struct dirent *_readdir_r (struct _reent *r, DIR *dp)
   451 	{
   452 	if (wreaddir(dp))
   453 		{
   454 		if (dp->UpdateNarrow()>=0)
   455 			return &dp->iCurrentNarrow;
   456 		else
   457 			r->_errno = EINVAL;
   458 		}
   459 
   460 	return 0;
   461 	}
   462 
   463 /**
   464 Sets the position (associated with the directory stream that dirp points to) 
   465 to the beginning of the directory. 
   466 Additionally, it causes the directory stream to refer to the current state of 
   467 the corresponding directory.
   468 @param dp Points to the directory stream of the directory to rewind.
   469 */
   470 EXPORT_C void rewinddir (DIR *dp)
   471 	{
   472 	wrewinddir(dp);
   473 	}
   474 
   475 /**
   476 closes the directory stream that dirp refers to. 
   477 The memory associated with the directory stream is released. 
   478 When this function returns, the value of dirp no longer point to 
   479 an accessible object of type DIR
   480 @return a value of zero. On failure, it returns -1
   481 @param dp Is the directory pointer to close (from opendir()).
   482 */
   483 EXPORT_C int closedir (DIR *dp)
   484 	{
   485 	return wclosedir(dp);
   486 	}
   487 
   488 /**
   489 sets the position of the next readdir() operation on the directory 
   490 stream specified by dp to the position specified by index
   491 @param dp Points to the directory stream of the directory
   492 @param index
   493 */
   494 EXPORT_C void seekdir(DIR *dp,off_t index)
   495 	{
   496 	wseekdir(dp,index);
   497 	}
   498 
   499 /**
   500 Returns the current location associated with the directory stream dir.
   501 @return the current location in the directory stream or -1 if an error occurs. 
   502 @param dp Points to the directory stream of the directory
   503 */
   504 EXPORT_C off_t telldir(const DIR *dp)
   505 	{
   506 	return wtelldir(dp);
   507 	}
   508 
   509 } // extern "C"