1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/LPOSIX/POSIX.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,509 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// POSIX systems calls implemented over EPOC32
1.18 +//
1.19 +//
1.20 +
1.21 +#include "SYSIF.H"
1.22 +#include <unistd.h>
1.23 +#include <errno.h>
1.24 +#include "LPOSIX.H"
1.25 +#include <utf.h>
1.26 +#include <networking/dnd_err.h>
1.27 +
1.28 +GLDEF_C TInt GetFullPath(TParse& aParse, const TText16* upath, RFs& aSession, TDes* aFileName)
1.29 +//
1.30 +// Parse a path of the form "[C:][\]AAA\..\.\BBB\xxx" where:
1.31 +// . indicates the current directory
1.32 +// .. indicates move to the parent directory
1.33 +// An optional "\" at the start of the path indicates the path is not relative to the current path,
1.34 +// and is implied if the drive specifier is present
1.35 +// If aFileName is non-NULL then the final component is a filename and should be copied into
1.36 +// the aFileName descriptor.
1.37 +//
1.38 + {
1.39 +
1.40 + TInt r;
1.41 + TBuf<3> drive;
1.42 + TFileName nextBit;
1.43 + TText16 c=*upath;
1.44 +
1.45 + if (c && upath[1]==KDriveDelimiter)
1.46 + {
1.47 + // drive name specified
1.48 + if (c==L'?')
1.49 + drive.Zero(); // use "?:" to mean scan across drives
1.50 + else
1.51 + {
1.52 + drive.Copy(TPtrC16(upath, 2));
1.53 + drive.UpperCase();
1.54 + }
1.55 + upath+=2;
1.56 + drive.Append(TChar(KPathDelimiter)); // enforce absoluteness
1.57 + }
1.58 + else
1.59 + {
1.60 + // no leading drive specifier
1.61 + drive.Zero();
1.62 + if (c==KPathDelimiter||c==L'/')
1.63 + {
1.64 + upath+=1;
1.65 + drive.Append(TChar(KPathDelimiter));
1.66 + }
1.67 + }
1.68 + r = aSession.Parse(drive, aParse);
1.69 +
1.70 + // upath now looks like a relative pathname, to be added onto
1.71 + // aParse a directory at a time. Note that '/' is not allowed in
1.72 + // EPOC32 file or directory names, so treat it as an alternative separator
1.73 +
1.74 + c=*upath;
1.75 + while (c && (r==KErrNone))
1.76 + {
1.77 + const TText16* ustart=upath;
1.78 + do
1.79 + c=*upath++;
1.80 + while (c && c!=KPathDelimiter && c!=L'/');
1.81 +
1.82 + TInt len=(upath-ustart)-1; // excludes delimiter
1.83 + if (len==0)
1.84 + continue;
1.85 + if (ustart[0]==L'.')
1.86 + {
1.87 + if (len==1)
1.88 + continue; // directory . ignored
1.89 + if (len==2 && ustart[1]==L'.')
1.90 + {
1.91 + // directory ..
1.92 + (void) aParse.PopDir(); // just stick at root dir, no errors
1.93 + continue;
1.94 + }
1.95 + }
1.96 + if (len>=KMaxFileName)
1.97 + return ENAMETOOLONG;
1.98 + if (c==L'\0' && aFileName!=NULL)
1.99 + {
1.100 + // it's the trailing filename
1.101 + aFileName->Copy(TPtrC16(ustart, len));
1.102 + break;
1.103 + }
1.104 + else
1.105 + {
1.106 + // it's a component of the accumulating path
1.107 + nextBit.Copy(TPtrC16(ustart, len));
1.108 + r = aParse.AddDir(nextBit);
1.109 + }
1.110 + }
1.111 + return(r);
1.112 + }
1.113 +
1.114 +
1.115 +GLDEF_C TInt GetFullFile(TFileName& aName, const TText16* upath, RFs& aSession)
1.116 +// Use GetFullPath to establish the pathname, then add the filename onto the end
1.117 + {
1.118 + TParse path;
1.119 + TInt err = GetFullPath(path,upath,aSession,&aName);
1.120 + if (err!=KErrNone)
1.121 + return err;
1.122 + // Wildcard drive letter for searching across drives
1.123 + if (upath[0]==L'?' && upath[1]==L':')
1.124 + {
1.125 + TFindFile search(aSession);
1.126 + err=search.FindByDir(aName,path.Path());
1.127 + if (!err)
1.128 + {
1.129 + aName=search.File();
1.130 + return KErrNone;
1.131 + }
1.132 + }
1.133 + err = path.SetNoWild(path.DriveAndPath(),NULL,&aName);
1.134 + if (!err)
1.135 + aName = path.FullName();
1.136 + return err;
1.137 + }
1.138 +
1.139 +
1.140 +// Set errno from an E32STD.H error code or a STDLIB errno value
1.141 +
1.142 +static const TUint8 EPOCtoERRNO[43] = {
1.143 + ENOENT, // KErrNotFound=(-1);
1.144 + 0, // KErrGeneral=(-2);
1.145 + EINTR, // KErrCancel=(-3);
1.146 + ENOMEM, // KErrNoMemory=(-4);
1.147 + ENOSYS, // KErrNotSupported=(-5);
1.148 + EINVAL, // KErrArgument=(-6);
1.149 + 0, // KErrTotalLossOfPrecision=(-7);
1.150 + 0, // KErrBadHandle=(-8);
1.151 + ERANGE, // KErrOverflow=(-9);
1.152 + ERANGE, // KErrUnderflow=(-10);
1.153 + EEXIST, // KErrAlreadyExists=(-11);
1.154 + ENOENT, // KErrPathNotFound=(-12);
1.155 + EPIPE, // KErrDied=(-13);
1.156 + EACCES, // KErrInUse=(-14);
1.157 + EPIPE, // KErrServerTerminated=(-15);
1.158 + EBUSY, // KErrServerBusy=(-16);
1.159 + 0, // KErrCompletion=(-17);
1.160 + 0, // KErrNotReady=(-18);
1.161 + 0, // KErrUnknown=(-19);
1.162 + 0, // KErrCorrupt=(-20);
1.163 + EACCES, // KErrAccessDenied=(-21);
1.164 + EACCES, // KErrLocked=(-22);
1.165 + 0, // KErrWrite=(-23);
1.166 + ENODEV, // KErrDisMounted=(-24);
1.167 + EPIPE, // KErrEof=(-25);
1.168 + ENOSPC, // KErrDiskFull=(-26);
1.169 + 0, // KErrBadDriver=(-27);
1.170 + EINVAL, // KErrBadName=(-28);
1.171 + ECOMM, // KErrCommsLineFail=(-29);
1.172 + ECOMM, // KErrCommsFrame=(-30);
1.173 + ECOMM, // KErrCommsOverrun=(-31);
1.174 + ECOMM, // KErrCommsParity=(-32);
1.175 + ETIMEDOUT, // KErrTimedOut=(-33);
1.176 + ECONNREFUSED, // KErrCouldNotConnect=(-34);
1.177 + 0, // KErrCouldNotDisconnect=(-35);
1.178 + EPIPE, // KErrDisconnected=(-36);
1.179 + 0, // KErrBadLibraryEntryPoint=(-37);
1.180 + 0, // KErrBadDescriptor=(-38);
1.181 + 0, // KErrAbort=(-39);
1.182 + 0, // KErrTooBig=(-40);
1.183 + EDOM, // KErrDivideByZero=(-41);
1.184 + EDOM, // KErrBadPower=(-42);
1.185 + ENOSPC // KErrDirFull=(-43);
1.186 + };
1.187 +
1.188 +
1.189 +EXPORT_C int MapError(TInt err, int& anErrno)
1.190 + {
1.191 + if (err==0)
1.192 + return err; // i.e. return 0 without changing errno
1.193 + TInt ret=err;
1.194 + if (err<KErrNone && err>=KErrDirFull)
1.195 + {
1.196 + ret=EPOCtoERRNO[-1-err];
1.197 + if (ret==0)
1.198 + ret=err; // no sensible translation
1.199 + }
1.200 + else if ((err == KErrDndNameNotFound) || (err == KErrDndAddrNotFound))
1.201 + // KErrDndNameNotFound Returned when no data found for GetByName
1.202 + // KErrDndAddrNotFound Returned when no data found for GetByAddr
1.203 + {
1.204 + ret=ENOENT;
1.205 + }
1.206 + anErrno=ret; // KErr* values are negative, so will be distinct anyway
1.207 + return -1;
1.208 + }
1.209 +
1.210 +
1.211 +
1.212 +// Directory enumeration
1.213 +
1.214 +NONSHARABLE_STRUCT(__EPOC32_WDIR) : public CBase // aka "class __EPOC32_WDIR with everything public"
1.215 + {
1.216 +public:
1.217 + __EPOC32_WDIR(struct _reent* aContext) : iContext(aContext) {}
1.218 + ~__EPOC32_WDIR();
1.219 +
1.220 + TInt Open();
1.221 + TInt Open(const TDesC& aPath);
1.222 + TInt Open(const wchar_t *_path);
1.223 +
1.224 + virtual TInt UpdateNarrow();
1.225 + struct _reent *iContext;
1.226 + HBufC* iPath;
1.227 + CDir* iEntries;
1.228 + TInt iIndex; // counting down, 0 means "finished"
1.229 + struct wdirent iCurrent;
1.230 + TBuf16<KMaxFileName> iCurrentName;
1.231 + };
1.232 +
1.233 +TInt __EPOC32_WDIR::UpdateNarrow()
1.234 +{
1.235 + return -1; //this is not supported.
1.236 +}
1.237 +
1.238 +
1.239 +NONSHARABLE_STRUCT(__EPOC32_DIR) : public __EPOC32_WDIR
1.240 + {
1.241 +public:
1.242 + __EPOC32_DIR(struct _reent* aContext) : __EPOC32_WDIR(aContext) {}
1.243 + ~__EPOC32_DIR() {}
1.244 +
1.245 + virtual TInt UpdateNarrow();
1.246 + struct dirent iCurrentNarrow;
1.247 + TBuf8<KMaxFileName> iCurrentNarrowName;
1.248 + };
1.249 +
1.250 +
1.251 +TInt __EPOC32_DIR::UpdateNarrow()
1.252 +{
1.253 + //update the narrow one
1.254 +
1.255 + TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(iCurrentNarrowName, iCurrentName);
1.256 + if (ret >= 0)
1.257 + {
1.258 + iCurrentNarrow.d_namlen=(short)iCurrentNarrowName.Length();
1.259 + iCurrentNarrow.d_name = (char*)iCurrentNarrowName.PtrZ();
1.260 + }
1.261 + return ret;
1.262 +}
1.263 +
1.264 +
1.265 +__EPOC32_WDIR::~__EPOC32_WDIR()
1.266 + {
1.267 + delete iPath;
1.268 + delete iEntries;
1.269 + }
1.270 +
1.271 +TInt __EPOC32_WDIR::Open(const wchar_t *_path)
1.272 + {
1.273 + MSystemInterface& sysIf=Interface(iContext);
1.274 + TParse name;
1.275 + TInt err = sysIf.ResolvePath(name,_path,NULL);
1.276 + if (!err)
1.277 + err = Open(name.DriveAndPath());
1.278 + if (err)
1.279 + MapError(err,iContext->_errno);
1.280 + return err;
1.281 + }
1.282 +
1.283 +TInt __EPOC32_WDIR::Open(const TDesC& aPath)
1.284 + {
1.285 + delete iPath;
1.286 + iPath=aPath.Alloc(); //allocate space for a hbufc and initialise it to the TDesC contents
1.287 + return Open();
1.288 + }
1.289 +
1.290 +TInt __EPOC32_WDIR::Open()
1.291 + {
1.292 + delete iEntries;
1.293 + iEntries=0;
1.294 + iIndex=-1;
1.295 + if (iPath==0)
1.296 + return ENOMEM;
1.297 + RFs session;
1.298 + TInt err=session.Connect();
1.299 + if (err)
1.300 + return err;
1.301 + err=session.GetDir(*iPath,KEntryAttMaskSupported,ESortByName+EDescending,iEntries);
1.302 + session.Close();
1.303 + if (!err)
1.304 + iIndex=iEntries->Count();
1.305 + return err;
1.306 + }
1.307 +
1.308 +extern "C" {
1.309 +
1.310 +/**
1.311 +Resets the position to the beginning of the directory.
1.312 +@param dp directory
1.313 +*/
1.314 +EXPORT_C void wrewinddir (WDIR *dp)
1.315 + {
1.316 + if (dp==0)
1.317 + return;
1.318 + (void) dp->Open(); // POSIX doesn't allow for rewind failing
1.319 + }
1.320 +
1.321 +/**
1.322 +Closes the directory.
1.323 +@param dp directory to close.
1.324 +*/
1.325 +EXPORT_C int wclosedir (WDIR *dp)
1.326 + {
1.327 + delete dp;
1.328 + return 0;
1.329 + }
1.330 +
1.331 +/**
1.332 +Opens a directory.
1.333 +@return a pointer to the dir object.
1.334 +This object describes the directory
1.335 +and is used in subsequent operations on the directory
1.336 +If error, returns NULL.
1.337 +@param _path path to the directory to be opened.
1.338 +*/
1.339 +EXPORT_C DIR *opendir (const char *_path)
1.340 + {
1.341 + return _opendir_r(_REENT,_path);
1.342 + }
1.343 +
1.344 +/** A wide-character version of opendir()
1.345 +*/
1.346 +EXPORT_C WDIR *wopendir (const wchar_t *_path)
1.347 + {
1.348 + return _wopendir_r(_REENT,_path);
1.349 + }
1.350 +
1.351 +/** A reentrant version of opendir().
1.352 +*/
1.353 +EXPORT_C DIR *_opendir_r (struct _reent *r, const char *_path)
1.354 + {
1.355 +
1.356 + wchar_t _widepath[KMaxFileName+1];
1.357 +
1.358 + if (mbstowcs(_widepath, _path, KMaxFileName) < 0)
1.359 + {
1.360 + MapError(EILSEQ,r->_errno);
1.361 + return 0;
1.362 + }
1.363 + //coverity[alloc_fn]
1.364 + //coverity[assign]
1.365 +
1.366 + DIR* dp = new __EPOC32_DIR(r);
1.367 + if (dp==0)
1.368 + {
1.369 + r->_errno=ENOMEM;
1.370 + return 0;
1.371 + }
1.372 +
1.373 + //coverity[leave_without_push]
1.374 +
1.375 + TInt err = dp->Open(_widepath);
1.376 + if (err)
1.377 + {
1.378 + delete dp;
1.379 + return 0;
1.380 + }
1.381 + return dp;
1.382 + }
1.383 +
1.384 +/** A reentrant version of wopendir().
1.385 +*/
1.386 +EXPORT_C WDIR *_wopendir_r (struct _reent *r, const wchar_t *_path)
1.387 + {
1.388 +
1.389 + //coverity[alloc_fn]
1.390 + //coverity[assign]
1.391 +
1.392 + WDIR* dp = new __EPOC32_WDIR(r);
1.393 + if (dp==0)
1.394 + {
1.395 + r->_errno=ENOMEM;
1.396 + return 0;
1.397 + }
1.398 + //coverity[leave_without_push]
1.399 +
1.400 + TInt err = dp->Open(_path);
1.401 + if (err)
1.402 + {
1.403 + delete dp;
1.404 + return 0;
1.405 + }
1.406 + return dp;
1.407 + }
1.408 +
1.409 +/**
1.410 +Sets the index position of the directory stream specified by dp
1.411 +to the position specified by index.
1.412 +*/
1.413 +EXPORT_C void wseekdir(WDIR *dp,off_t index)
1.414 + {
1.415 + dp->iIndex=index;
1.416 + }
1.417 +
1.418 +EXPORT_C off_t wtelldir(const WDIR *dp)
1.419 + {
1.420 + return dp->iIndex;
1.421 + }
1.422 +
1.423 +EXPORT_C struct wdirent *wreaddir (WDIR *dp)
1.424 + {
1.425 + if (dp->iIndex<=0)
1.426 + return 0;
1.427 + struct wdirent *ep=&dp->iCurrent;
1.428 + const TEntry& entry=(*dp->iEntries)[--(dp->iIndex)];
1.429 + // in practice, these files must have been created as "X:\something", so they
1.430 + // can't really be longer than KMaxFileName-3
1.431 + dp->iCurrentName.Copy(entry.iName);
1.432 + dp->iCurrentName.ZeroTerminate();
1.433 + ep->d_namlen=(short)dp->iCurrentName.Length();
1.434 + ep->d_name=(wchar_t*)dp->iCurrentName.PtrZ();
1.435 + return ep;
1.436 + }
1.437 +
1.438 +/**
1.439 +Returns a pointer to a dirent structure representing
1.440 +the next directory entry in the directory stream pointed to be dir.
1.441 +It returns NULL on reaching the end-of-file or if an error occurred.
1.442 +@return a pointer to a dirent structure, or NULL if an error occurs
1.443 +or end-of-file is reached.
1.444 +@param dp Points to the directory stream of the directory.
1.445 +*/
1.446 +EXPORT_C struct dirent *readdir (DIR *dp)
1.447 + {
1.448 + return _readdir_r(_REENT, dp);
1.449 + }
1.450 +
1.451 +/** A reentrant version of readdir().
1.452 +*/
1.453 +EXPORT_C struct dirent *_readdir_r (struct _reent *r, DIR *dp)
1.454 + {
1.455 + if (wreaddir(dp))
1.456 + {
1.457 + if (dp->UpdateNarrow()>=0)
1.458 + return &dp->iCurrentNarrow;
1.459 + else
1.460 + r->_errno = EINVAL;
1.461 + }
1.462 +
1.463 + return 0;
1.464 + }
1.465 +
1.466 +/**
1.467 +Sets the position (associated with the directory stream that dirp points to)
1.468 +to the beginning of the directory.
1.469 +Additionally, it causes the directory stream to refer to the current state of
1.470 +the corresponding directory.
1.471 +@param dp Points to the directory stream of the directory to rewind.
1.472 +*/
1.473 +EXPORT_C void rewinddir (DIR *dp)
1.474 + {
1.475 + wrewinddir(dp);
1.476 + }
1.477 +
1.478 +/**
1.479 +closes the directory stream that dirp refers to.
1.480 +The memory associated with the directory stream is released.
1.481 +When this function returns, the value of dirp no longer point to
1.482 +an accessible object of type DIR
1.483 +@return a value of zero. On failure, it returns -1
1.484 +@param dp Is the directory pointer to close (from opendir()).
1.485 +*/
1.486 +EXPORT_C int closedir (DIR *dp)
1.487 + {
1.488 + return wclosedir(dp);
1.489 + }
1.490 +
1.491 +/**
1.492 +sets the position of the next readdir() operation on the directory
1.493 +stream specified by dp to the position specified by index
1.494 +@param dp Points to the directory stream of the directory
1.495 +@param index
1.496 +*/
1.497 +EXPORT_C void seekdir(DIR *dp,off_t index)
1.498 + {
1.499 + wseekdir(dp,index);
1.500 + }
1.501 +
1.502 +/**
1.503 +Returns the current location associated with the directory stream dir.
1.504 +@return the current location in the directory stream or -1 if an error occurs.
1.505 +@param dp Points to the directory stream of the directory
1.506 +*/
1.507 +EXPORT_C off_t telldir(const DIR *dp)
1.508 + {
1.509 + return wtelldir(dp);
1.510 + }
1.511 +
1.512 +} // extern "C"