os/ossrv/genericopenlibs/cstdlib/USTLIB/FDESC.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1997-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 //
    15 
    16 #include "FDESC.H"
    17 #include "LPOSIX.H"
    18 #include "LTIME.H"
    19 #include <string.h>
    20 #include <stdio_r.h>
    21 #include <fcntl.h>		// for struct stat
    22 #include <sys/errno.h>		// for ENOTSOCK
    23 #include <sys/ioctl.h>
    24 #include <c32comm.h>
    25 
    26 #include "POSIXIF.H"	// for details of CPosixRequest::iLink
    27 
    28 // Cleanup support
    29 
    30 void CFileDescBase::Cleanup(TAny *aPtr)
    31 	{
    32 	((CFileDescBase*)aPtr)->Close();
    33 	}
    34 
    35 void CFileDescBase::PushLC()
    36 	{
    37 	CleanupStack::PushL(TCleanupItem(Cleanup,this));
    38 	}
    39 
    40 // Private constructor
    41 
    42 inline TPosixRequestQueue::TPosixRequestQueue() 
    43 : TSglQue<CPosixRequest>(_FOFF(CPosixRequest,iLink)) 
    44 	{}
    45 
    46 CFileDescBase::CFileDescBase() : iReadTimeout(-1)
    47 	{
    48 	}
    49 
    50 // A CFileDescBase factory function, for "named" file-like objects
    51 
    52 //CFileDescBase* CFileDescBase::Open(RFs& aSession, const char* name, int mode, int perms, TInt& err)
    53 //CFileDescBase* CFileDescBase::Open(RFs& aSession, const wchar_t* name, int mode, int perms, TInt& err)
    54 CFileDescBase* CFileDescBase::Open(RSessionBase& aSession, const wchar_t* name, int mode, int perms, TInt& err)
    55 	{
    56 	CFileDescBase* ret=0;
    57 
    58 	if (wcscmp(name,L"CON:")==0)
    59 		ret= new CTtyDesc;	// NB. This won't be the default stdin/stdout/stderr console
    60 	else
    61 	if (wcscmp(name,L"NUL:")==0)
    62 		ret= new CFileDescBase;
    63 	else
    64 	if (wcscmp(name,L"TMP:")==0)
    65 		{
    66 		RFs& rfs = static_cast<RFs&>(aSession);
    67 		TParse path;
    68 		err=GetFullPath(path,(const TText16*)WIDEP_tmpdir, rfs,NULL);
    69 		if (err)
    70 			return 0;
    71 		CTempFileDesc* tmp= new CTempFileDesc;
    72 		if (tmp)
    73 			{
    74 			err=tmp->Open(rfs,path.DriveAndPath());
    75 			if (err)
    76 				{
    77 				delete tmp;
    78 				return 0;
    79 				}
    80 			}
    81 		ret=tmp;
    82 		}
    83 	else if	((L'C' == name[0]) && (L'O' == name[1]) && (L'M' == name[2]) && (L':' == name[4]) && ((name[3] >= L'1') && (name[3] <= L'9')) ||
    84 			(L'I' == name[0]) && (L'R' == name[1]) && (L'C' == name[2]) && (L'O' == name[3]) && (L'M' == name[4]) && (L':' == name[6]) && ((name[5] >= L'1') && (name[5] <= L'9')))
    85 		{
    86 
    87 		RCommServ& rcs = static_cast<RCommServ&>(aSession);
    88 		if (!rcs.Handle())	
    89 			{
    90 			err=rcs.Connect();	//connect to the server
    91 			if (err)
    92 				return 0;
    93 			}
    94 		CSerialDesc * tmp = new CSerialDesc;
    95 		if (tmp)
    96 			{
    97 			RCommServ& rcs = static_cast<RCommServ&>(aSession);
    98 			CleanupStack::PushL(tmp);
    99 			err = tmp->Open(rcs, name, mode, perms);
   100 			CleanupStack::Pop(tmp);
   101 			if (err)
   102 				{
   103 				delete tmp;
   104 				return 0;
   105 				}
   106 			}
   107 		ret = tmp;
   108 		}
   109 	else
   110 		{
   111 		TFullName fullName;
   112 		RFs& rfs = static_cast<RFs&>(aSession);
   113 		err=GetFullFile(fullName,(const TText16*)name,rfs);
   114 		if (err)
   115 			return 0;
   116 		CFileDesc* f= new CFileDesc;
   117 		if (f)
   118 			{
   119 			err=f->Open(rfs,fullName,mode,perms);
   120 			if (err)
   121 				{
   122 				delete f;
   123 				return 0;
   124 				}
   125 			}
   126 		ret=f;
   127 		}
   128 	err=(ret==0)? KErrNoMemory:KErrNone;
   129 	return ret;
   130 	}
   131 
   132 // Useful default implementations for CFileDescBase virtual functions.
   133 
   134 TInt CFileDescBase::LSeek (int& offset, int)
   135 	{
   136 	// minimal implementation for devices which can't seek
   137 	offset=0;
   138 	return KErrNone;
   139 	}
   140 
   141 void CFileDescBase::Read (TDes8& aBuf, TRequestStatus& aStatus)
   142 	{
   143 	// minimal implementation for /dev/null
   144 	aBuf.Zero();	// set length to zero
   145 	TRequestStatus* sp=&aStatus;
   146 	User::RequestComplete(sp,KErrNone);
   147 	}
   148 
   149 void CFileDescBase::ReadCancel() {}
   150 
   151 TInt CFileDescBase::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus)
   152 	{
   153 	return aStatus;
   154 	}
   155 
   156 
   157 TInt CFileDescBase::FStat (struct stat *st)
   158 	{
   159 	// minimal implementation: 
   160 	// I am a character device about which little is known
   161 	st->st_mode = S_IFCHR;
   162 	st->st_blksize=0;
   163 	return KErrNone;
   164 	}
   165 
   166 void CFileDescBase::Complete (TRequestStatus& aStatus, TInt aResult)
   167 	{
   168 	TRequestStatus* sp=&aStatus;
   169 	User::RequestComplete(sp,aResult);
   170 	}
   171 
   172 void CFileDescBase::Write (TDes8& /*aBuf*/, TRequestStatus& aStatus)
   173 	{
   174 	// minimal implementation for /dev/null
   175 	// we will claim to have written all of the data
   176 	Complete(aStatus,KErrNone);
   177 	}
   178 
   179 void CFileDescBase::WriteCancel() {}
   180 
   181 TInt CFileDescBase::WriteCompletion (TDes8& /*aBuf*/, TInt aStatus)
   182 	{
   183 	return aStatus;
   184 	}
   185 
   186 void CFileDescBase::Sync (TRequestStatus& aStatus)
   187 	{
   188 	// minimal implementation for /dev/null
   189 	Complete(aStatus,KErrNone);
   190 	}
   191 
   192 void CFileDescBase::SyncCancel() {}
   193 
   194 void CFileDescBase::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus)
   195 	{
   196 	// minimal implementation for /dev/null and other synchronous devices
   197 	Complete(aStatus,KErrNone);
   198 	}
   199 
   200 void CFileDescBase::IoctlCancel() 
   201 	{
   202 	return;	// suitable for all synchronous ioctls
   203 	}
   204 
   205 TInt CFileDescBase::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
   206 	{
   207 	TInt ret=aStatus;
   208 	if (ret!=KErrNone)
   209 		return ret;
   210 	int *param=REINTERPRET_CAST(int*,aParam);
   211 	switch (aCmd)
   212 		{
   213 	case E32IONREAD:
   214 		*param=0;	// claim that no data is available
   215 		break;
   216 	case E32IOSELECT:
   217 		*param=(*param)&(E32SELECT_READ|E32SELECT_WRITE);	// but don't block
   218 		break;
   219 	default:
   220 		ret=KErrNotSupported;
   221 		break;
   222 		}
   223 	return ret;
   224 	}
   225 
   226 // A CFileDescBase factory function, for socket objects
   227 
   228 CFileDescBase* CFileDescBase::Socket(RSocketServ& aSs, int family, int style, int protocol, TInt& err)
   229 	{
   230 	// connect to the Socket Server if necessary
   231 	if (aSs.Handle()==0)
   232 		{
   233 		err=aSs.Connect(TUint(-1));	// allow arbitrary number of requests
   234 		if (err)
   235 			return 0;
   236 		}
   237 	CSocketDesc* s= new CSocketDesc;
   238 	if (s==0)
   239 		{
   240 		err=KErrNoMemory;
   241 		return 0;
   242 		}
   243 	err=s->Socket(aSs,family,style,protocol);
   244 	if (err)
   245 		{
   246 		delete s;
   247 		return 0;
   248 		}
   249 	return s;
   250 	}
   251 
   252 // minimal implementation of sockets, useful for all non-socket descriptors
   253 
   254 void CFileDescBase::RecvFrom(TDes8& /*aDesc*/, TSockAddr& /*from*/, int /*flags*/, TRequestStatus& aStatus)
   255 	{
   256 	// minimal implementation
   257 	Complete(aStatus,ENOTSOCK);
   258 	}
   259 
   260 void CFileDescBase::RecvFromCancel () {}
   261 
   262 TInt CFileDescBase::RecvFromCompletion(TInt& /*aLength*/, TInt aStatus)
   263 	{
   264 	return aStatus;
   265 	}
   266 
   267 void CFileDescBase::SendTo(TDes8& /*aDesc*/, TSockAddr& /*to*/, int /*flags*/, TRequestStatus& aStatus)
   268 	{
   269 	// minimal implementation
   270 	Complete(aStatus,ENOTSOCK);
   271 	}
   272 
   273 void CFileDescBase::SendToCancel () {}
   274 
   275 TInt CFileDescBase::SendToCompletion(TDes8& /*aDesc*/, TInt aStatus)
   276 	{
   277 	return aStatus;
   278 	}
   279 
   280 void CFileDescBase::Shutdown(TUint /*aHow*/,TRequestStatus& aStatus)
   281 	{
   282 	// minimal implementation
   283 	Complete(aStatus,ENOTSOCK);
   284 	}
   285 
   286 void CFileDescBase::ShutdownCancel () {}
   287 
   288 TInt CFileDescBase::Bind(TSockAddr& /*anAddr*/)
   289 	{
   290 	return ENOTSOCK;
   291 	}
   292 
   293 TInt CFileDescBase::Listen(TUint /*qSize*/)
   294 	{
   295 	return ENOTSOCK;
   296 	}
   297 
   298 void CFileDescBase::Accept(CSocketDesc*& /*aNewSocket*/, TRequestStatus& aStatus, RSocketServ& /*aSs*/)
   299 	{
   300 	// minimal implementation
   301 	Complete(aStatus,ENOTSOCK);
   302 	}
   303 
   304 void CFileDescBase::AcceptCancel () {}
   305 
   306 void CFileDescBase::Connect(TSockAddr& /*anAddr*/,TRequestStatus& aStatus)
   307 	{
   308 	// minimal implementation
   309 	Complete(aStatus,ENOTSOCK);
   310 	}
   311 
   312 void CFileDescBase::ConnectCancel () {}
   313 
   314 TInt CFileDescBase::SockName(int /*anEnd*/, TSockAddr& /*anAddr*/)
   315 	{
   316 	return ENOTSOCK;
   317 	}
   318 
   319 TInt CFileDescBase::GetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDes8& /*anOption*/)
   320 	{
   321 	return ENOTSOCK;
   322 	}
   323 
   324 TInt CFileDescBase::SetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDesC8& /*anOption*/)
   325 	{
   326 	return ENOTSOCK;
   327 	}
   328 
   329 // Queue handling
   330 
   331 void CFileDescBase::AddLast(CPosixRequest& aRequest, IOQueues aQueue)
   332 	{
   333 	TPosixRequestQueue& queue = iQueues[aQueue];
   334 	queue.AddLast(aRequest);
   335 	if (queue.IsFirst(&aRequest))
   336 		aRequest.StartAsynch();	// queue was empty, so start straight away
   337 	}
   338 
   339 void CFileDescBase::Remove(CPosixRequest& aRequest, IOQueues aQueue)
   340 	{
   341 	TPosixRequestQueue& queue = iQueues[aQueue];
   342 	TBool wasFirst = queue.IsFirst(&aRequest);
   343 	queue.Remove(aRequest);
   344 	if (wasFirst)
   345 		{
   346 		if (!queue.IsEmpty())
   347 			queue.First()->StartAsynch();	// start the next outstanding request
   348 		}
   349 	}
   350 
   351 
   352 // Generic (non-virtual) handling for Close
   353 
   354 TInt CFileDescBase::Close()
   355 	{ 
   356 	TInt err=KErrNone;
   357 	if (--iDupCount < 0)
   358 		{
   359 		err=FinalClose();
   360 		delete this;
   361 		}
   362 	return err;
   363 	}
   364 
   365 TInt CFileDescBase::FinalClose()
   366 	{
   367 	return KErrNone;
   368 	}
   369 
   370 
   371 // Simple implementation of File handling
   372 
   373 static int MapMode(int aMode, TUint& fMode)
   374 	{
   375 	// EPOC32 doesn't support Write-Only
   376 	
   377 	if (aMode & (O_WRONLY|O_RDWR))
   378 		{
   379 		fMode = EFileWrite;
   380 		fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareAny;	
   381 		}
   382 	else
   383 		{
   384 		fMode = EFileRead;
   385 		fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareReadersOnly;	
   386 		}
   387 
   388 	fMode |= (aMode & O_TEXT) ? EFileStreamText : EFileStream;
   389 
   390 	return aMode & (O_CREAT|O_TRUNC|O_APPEND|O_EXCL);
   391 	}
   392 
   393 CFileDesc::CFileDesc()
   394 	:CFileDescBase(), iSize(EBufferSize), iExt(-1)
   395 	{}
   396 
   397 CFileDesc::~CFileDesc()
   398 	{
   399 	iFile.Close();
   400 	delete [] iBuffer;
   401 	}
   402 
   403 TInt CFileDesc::FinalClose()
   404 	{
   405 	return DoSync();
   406 	}
   407 	
   408 TInt CFileDesc::Open(RFs& aSession, const TDesC& aName, int mode, int /*perms*/)
   409 	{
   410 	TInt err;
   411 	TUint fMode;
   412 
   413 	iDrive=(TInt16)TDriveUnit(aName);
   414 
   415 	// Create  = make new file, can return KErrAlreadyExists
   416 	// Open    = open an existing file, can return KErrPathNotFound or KErrNotFound
   417 	// Replace = open a new file, zapping the existing one if necessary
   418 
   419 	int mapped=MapMode(mode, fMode);
   420 	switch (mapped)
   421 		{
   422 		case O_CREAT|O_EXCL:
   423 			err = iFile.Create(aSession, aName, fMode);
   424 			break;
   425 		case O_CREAT|O_TRUNC:
   426 			err = iFile.Replace(aSession, aName, fMode);
   427 			break;
   428 		case O_TRUNC:
   429 			err = iFile.Open(aSession, aName, fMode);
   430 			if (err == KErrPathNotFound)
   431 			    {
   432 			    // missing directories etc, so fail directly
   433 			    }
   434 			else
   435 			    {
   436 			    iFile.Close();
   437 			    err = iFile.Replace(aSession, aName, fMode);
   438 			    }
   439 			break;
   440 
   441 		// Everything else is assumed to mean open existing file,
   442 		// If the file isn't there, O_CREAT implies that we should make it
   443 		default:
   444 			err = iFile.Open(aSession, aName, fMode);
   445 			if (err == KErrNotFound && (mapped & O_CREAT))
   446 			    err = iFile.Create(aSession, aName, fMode);
   447 			if (err == KErrNone && (mapped & O_APPEND))
   448 			    {
   449 				iPos = Ext();
   450 				if (iPos < 0)
   451 					err = iPos;
   452 			    }
   453 			break;
   454 		}
   455 	if ((mode & O_BUFFERED) == 0)
   456 		iSize = 0;
   457 	return err;
   458 	}
   459 
   460 TInt CFileDesc::LSeek (int& offset, int whence)
   461 	{
   462 
   463 	TInt pos=offset;
   464 	TInt ext=Ext();
   465 	if (ext < 0)
   466 		return ext;
   467 
   468 	switch (whence)
   469 		{
   470 	case SEEK_SET:
   471 		break;
   472 	case SEEK_CUR:
   473 		pos += Pos();
   474 		break;
   475 	case SEEK_END:
   476 		pos += ext;
   477 		break;
   478 	default:
   479 		return KErrArgument;
   480 		}
   481 	TInt ret = KErrNone;
   482 	if (pos < 0)
   483 		{
   484 		pos = 0;
   485 		ret = KErrEof;
   486 		}
   487 	else if (pos > ext)
   488 		{
   489 		pos = ext;
   490 		ret = KErrEof;
   491 		}
   492 
   493 	switch (iState)
   494 		{
   495 	case EAlloc:
   496 		iPos = pos;
   497 		break;
   498 	case EReading:
   499 		{
   500 		TInt lag = iPos - pos;
   501 		if (lag >= 0 && lag <= (iEnd - iBuffer))
   502 			iPtr = iEnd - lag;
   503 		else
   504 			{
   505 			iPtr = iEnd;
   506 			iPos = pos;
   507 			}
   508 		}
   509 		break;
   510 	case EWriting:
   511 		if (pos != Pos())
   512 			{
   513 			ret = Flush();
   514 			if (ret == KErrNone)
   515 				iPos = pos;
   516 			}
   517 		break;
   518 		}
   519 	offset = pos;
   520 	return ret;
   521 	}
   522 
   523 void CFileDesc::MapStat(struct stat& st, const TTime& aModTime, TUint& aAttr)
   524     {
   525     st.st_mode = (aAttr&KEntryAttDir) ? S_IFDIR:S_IFREG;
   526     if ((aAttr&KEntryAttReadOnly)==0)
   527 	st.st_mode |= S_IWUSR;
   528     st.st_nlink = 1;
   529     st.st_mtime = as_time_t(aModTime);
   530     st.st_blksize=512;
   531     }
   532 
   533 TInt CFileDesc::FStat (struct stat* st)
   534 	{
   535 	TInt err;
   536 	TUint att;
   537 	TTime modtime;
   538 	
   539 	err = iFile.Att(att);
   540 	if (!err)
   541 	    {
   542 	    err = iFile.Modified(modtime);
   543 	    if (!err)
   544 		{
   545 		err=Ext();
   546 		if (err >= 0)
   547 		    {
   548 		    st->st_size = err;
   549 		    st->st_dev = st->st_rdev = iDrive;
   550 		    MapStat(*st, modtime, att);
   551 		    return 0;
   552 		    }
   553 		}
   554 	    }
   555 	return err;
   556 	}
   557 
   558 TInt CFileDesc::Alloc()
   559 	{
   560 	if (iSize)
   561 		{
   562 		iBuffer = new TUint8[iSize];
   563 		if (iBuffer == 0)
   564 			return KErrNoMemory;
   565 		}
   566 	return KErrNone;
   567 	}
   568 
   569 TInt CFileDesc::FileRead(TUint8* aPtr,TInt aLength)
   570 	{
   571 	TPtr8 ptr(aPtr,aLength);
   572 	TInt r=iFile.Read(iPos,ptr);
   573 	if (r == KErrNone)
   574 		{
   575 		r = ptr.Length();
   576 		iPos += r;
   577 		if (r < aLength)
   578 			iExt = iPos;
   579 		}
   580 	return r;
   581 	}
   582 
   583 TInt CFileDesc::FileWrite(TUint8* aPtr,TInt aLength)
   584 	{
   585 	TPtrC8 ptr(aPtr,aLength);
   586 	TInt r = iFile.Write(iPos,ptr);
   587 	if (r == KErrNone)
   588 		{
   589 		iPos += aLength;
   590 		if (iPos > iExt && iExt >= 0)
   591 			iExt = iPos;
   592 		}
   593 	return r;
   594 	}
   595 
   596 TInt CFileDesc::Flush()
   597 	{
   598 	if (iPtr > iBuffer)
   599 		{
   600 		TInt r = FileWrite(iBuffer, iPtr-iBuffer);
   601 		if (r < 0)
   602 			return r;
   603 		iPtr = iBuffer;
   604 		}
   605 	return KErrNone;
   606 	}
   607 
   608 TInt CFileDesc::DoRead (TDes8& aDesc)
   609 	{
   610 	if (iState != EReading)
   611 		{
   612 		TInt ret = (iState == EAlloc) ? Alloc() : Flush();
   613 		if (ret != KErrNone)
   614 			return ret;
   615 		iState = EReading;
   616 		iPtr = iEnd = iBuffer;
   617 		}
   618 
   619 	TUint8* p = (TUint8*) aDesc.Ptr();
   620 	TInt max = aDesc.MaxLength();
   621 	TInt avail = iEnd - iPtr;
   622 	TInt len = Min(max, avail);
   623 	if (len > 0)
   624 		{
   625 		p = Mem::Copy(p, iPtr, len);
   626 		iPtr += len;
   627 		max -= len;
   628 		}
   629 	if (max >= iSize)
   630 		{
   631 		TInt ret = FileRead(p, max);
   632 		if (ret < 0)
   633 			return ret;
   634 		p += ret;
   635 		}
   636 	else if (max > 0)
   637 		{
   638 		TInt ret = FileRead(iBuffer, Min(max + EReadAhead, iSize));
   639 		if (ret < 0)
   640 			return ret;
   641 		len = Min(max, ret);
   642 		p = Mem::Copy(p, iBuffer, len);
   643 		iPtr = iBuffer + len;
   644 		iEnd = iBuffer + ret;
   645 		}
   646 	aDesc.SetLength(p-aDesc.Ptr());
   647 	return KErrNone;
   648 	}
   649 
   650 void CFileDesc::Read (TDes8& aDesc, TRequestStatus& aStatus)
   651 	{
   652 	Complete(aStatus,DoRead(aDesc));
   653 	}
   654 
   655 TInt CFileDesc::DoWrite (TDes8& aDesc)
   656 	{
   657 	if (iState != EWriting)
   658 		{
   659 		if (iState == EAlloc)
   660 			{
   661 			TInt ret = Alloc();
   662 			if (ret != KErrNone)
   663 				return ret;
   664 			}
   665 		else
   666 			iPos -= iEnd - iPtr;
   667 
   668 		iState = EWriting;
   669 		iPtr = iBuffer;
   670 		iEnd = iBuffer + iSize;
   671 		}
   672 
   673 	TUint8* p = (TUint8*) aDesc.Ptr();
   674 	TInt max = aDesc.Length();
   675 	TInt avail = iEnd - iPtr;
   676 	TInt len = Min(max, avail);
   677 	if (len > 0)
   678 		{
   679 		iPtr = Mem::Copy(iPtr, p, len);
   680 		p += len;
   681 		max -= len;
   682 		}
   683 	if (max == 0)
   684 		return KErrNone;
   685 	TInt r=Flush();
   686 	if (r < 0)
   687 		return r;
   688 	if (max >= iSize)
   689 		return FileWrite(p, max);
   690 	iPtr = Mem::Copy(iPtr, p, max);
   691 	return KErrNone;
   692 	}
   693 
   694 void CFileDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
   695 	{
   696 	Complete(aStatus,DoWrite(aDesc));
   697 	}
   698 
   699 TInt CFileDesc::DoSync()
   700 	{
   701 	if (iState == EWriting)
   702 		{
   703 		TInt ret = Flush();
   704 		if (ret < 0)
   705 			return ret;
   706 		}
   707 	return iFile.Flush();
   708 	}
   709 
   710 void CFileDesc::Sync(TRequestStatus& aStatus)
   711 	{
   712 	Complete(aStatus,DoSync());
   713 	}
   714 
   715 TInt CFileDesc::Pos()
   716 	{
   717 	TInt pos = iPos;
   718 	if (iState == EReading)
   719 		pos -= (iEnd - iPtr);
   720 	else if (iState == EWriting)
   721 		pos += (iPtr - iBuffer);
   722 	return pos;
   723 	}
   724 
   725 TInt CFileDesc::Ext()
   726 	{
   727 	if (iExt < 0)
   728 		{
   729 		TInt r = iFile.Size(iExt);
   730 		if (r < 0)
   731 			return r;
   732 		}
   733 	return Max(iExt, Pos());
   734 	}
   735 
   736 TInt CFileDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
   737 	{
   738 	TInt ret=aStatus;
   739 	if (ret!=KErrNone)
   740 		return ret;
   741 	// some useful sums about the current state of the file
   742 	TInt curoff = Pos();
   743 	TInt size = Ext();
   744 	if (size < 0)
   745 		ret = size;
   746 	int *param=REINTERPRET_CAST(int*,aParam);
   747 	switch (aCmd)
   748 		{
   749 	case E32IONREAD:
   750 		if (ret==KErrNone)
   751 			*param=(size-curoff);
   752 		break;
   753 	case E32IOSELECT:
   754 		{
   755 		int mask=E32SELECT_WRITE;
   756 		if ((size-curoff)>0)
   757 			mask |= E32SELECT_READ;
   758 		*param=(*param)&mask;	// but don't block
   759 		}
   760 		break;
   761 	default:
   762 		ret=KErrNotSupported;
   763 		break;
   764 		}
   765 	return ret;
   766 	}
   767 
   768 // Extra support for temporary files
   769 
   770 TInt CTempFileDesc::Open(RFs& aSession, const TDesC& aPath)
   771 	{
   772 	iSession=aSession;
   773 	iDrive=(TInt16)TDriveUnit(aPath);
   774 	TInt err=iFile.Temp(aSession, aPath, iName, EFileShareAny);
   775 	return err;
   776 	}
   777 
   778 TInt CTempFileDesc::FinalClose()
   779 	{
   780 	iFile.Close();
   781 	TInt err=iSession.Delete(iName);
   782 	return err;
   783 	}