genericopenlibs/cstdlib/LPOSIX/POSIX.CPP
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     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"