genericopenlibs/cstdlib/USTLIB/FDESC.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 	}