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