1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/USTLIB/FDESC.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,783 @@
1.4 +// Copyright (c) 1997-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 +//
1.18 +
1.19 +#include "FDESC.H"
1.20 +#include "LPOSIX.H"
1.21 +#include "LTIME.H"
1.22 +#include <string.h>
1.23 +#include <stdio_r.h>
1.24 +#include <fcntl.h> // for struct stat
1.25 +#include <sys/errno.h> // for ENOTSOCK
1.26 +#include <sys/ioctl.h>
1.27 +#include <c32comm.h>
1.28 +
1.29 +#include "POSIXIF.H" // for details of CPosixRequest::iLink
1.30 +
1.31 +// Cleanup support
1.32 +
1.33 +void CFileDescBase::Cleanup(TAny *aPtr)
1.34 + {
1.35 + ((CFileDescBase*)aPtr)->Close();
1.36 + }
1.37 +
1.38 +void CFileDescBase::PushLC()
1.39 + {
1.40 + CleanupStack::PushL(TCleanupItem(Cleanup,this));
1.41 + }
1.42 +
1.43 +// Private constructor
1.44 +
1.45 +inline TPosixRequestQueue::TPosixRequestQueue()
1.46 +: TSglQue<CPosixRequest>(_FOFF(CPosixRequest,iLink))
1.47 + {}
1.48 +
1.49 +CFileDescBase::CFileDescBase() : iReadTimeout(-1)
1.50 + {
1.51 + }
1.52 +
1.53 +// A CFileDescBase factory function, for "named" file-like objects
1.54 +
1.55 +//CFileDescBase* CFileDescBase::Open(RFs& aSession, const char* name, int mode, int perms, TInt& err)
1.56 +//CFileDescBase* CFileDescBase::Open(RFs& aSession, const wchar_t* name, int mode, int perms, TInt& err)
1.57 +CFileDescBase* CFileDescBase::Open(RSessionBase& aSession, const wchar_t* name, int mode, int perms, TInt& err)
1.58 + {
1.59 + CFileDescBase* ret=0;
1.60 +
1.61 + if (wcscmp(name,L"CON:")==0)
1.62 + ret= new CTtyDesc; // NB. This won't be the default stdin/stdout/stderr console
1.63 + else
1.64 + if (wcscmp(name,L"NUL:")==0)
1.65 + ret= new CFileDescBase;
1.66 + else
1.67 + if (wcscmp(name,L"TMP:")==0)
1.68 + {
1.69 + RFs& rfs = static_cast<RFs&>(aSession);
1.70 + TParse path;
1.71 + err=GetFullPath(path,(const TText16*)WIDEP_tmpdir, rfs,NULL);
1.72 + if (err)
1.73 + return 0;
1.74 + CTempFileDesc* tmp= new CTempFileDesc;
1.75 + if (tmp)
1.76 + {
1.77 + err=tmp->Open(rfs,path.DriveAndPath());
1.78 + if (err)
1.79 + {
1.80 + delete tmp;
1.81 + return 0;
1.82 + }
1.83 + }
1.84 + ret=tmp;
1.85 + }
1.86 + 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')) ||
1.87 + (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')))
1.88 + {
1.89 +
1.90 + RCommServ& rcs = static_cast<RCommServ&>(aSession);
1.91 + if (!rcs.Handle())
1.92 + {
1.93 + err=rcs.Connect(); //connect to the server
1.94 + if (err)
1.95 + return 0;
1.96 + }
1.97 + CSerialDesc * tmp = new CSerialDesc;
1.98 + if (tmp)
1.99 + {
1.100 + RCommServ& rcs = static_cast<RCommServ&>(aSession);
1.101 + CleanupStack::PushL(tmp);
1.102 + err = tmp->Open(rcs, name, mode, perms);
1.103 + CleanupStack::Pop(tmp);
1.104 + if (err)
1.105 + {
1.106 + delete tmp;
1.107 + return 0;
1.108 + }
1.109 + }
1.110 + ret = tmp;
1.111 + }
1.112 + else
1.113 + {
1.114 + TFullName fullName;
1.115 + RFs& rfs = static_cast<RFs&>(aSession);
1.116 + err=GetFullFile(fullName,(const TText16*)name,rfs);
1.117 + if (err)
1.118 + return 0;
1.119 + CFileDesc* f= new CFileDesc;
1.120 + if (f)
1.121 + {
1.122 + err=f->Open(rfs,fullName,mode,perms);
1.123 + if (err)
1.124 + {
1.125 + delete f;
1.126 + return 0;
1.127 + }
1.128 + }
1.129 + ret=f;
1.130 + }
1.131 + err=(ret==0)? KErrNoMemory:KErrNone;
1.132 + return ret;
1.133 + }
1.134 +
1.135 +// Useful default implementations for CFileDescBase virtual functions.
1.136 +
1.137 +TInt CFileDescBase::LSeek (int& offset, int)
1.138 + {
1.139 + // minimal implementation for devices which can't seek
1.140 + offset=0;
1.141 + return KErrNone;
1.142 + }
1.143 +
1.144 +void CFileDescBase::Read (TDes8& aBuf, TRequestStatus& aStatus)
1.145 + {
1.146 + // minimal implementation for /dev/null
1.147 + aBuf.Zero(); // set length to zero
1.148 + TRequestStatus* sp=&aStatus;
1.149 + User::RequestComplete(sp,KErrNone);
1.150 + }
1.151 +
1.152 +void CFileDescBase::ReadCancel() {}
1.153 +
1.154 +TInt CFileDescBase::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus)
1.155 + {
1.156 + return aStatus;
1.157 + }
1.158 +
1.159 +
1.160 +TInt CFileDescBase::FStat (struct stat *st)
1.161 + {
1.162 + // minimal implementation:
1.163 + // I am a character device about which little is known
1.164 + st->st_mode = S_IFCHR;
1.165 + st->st_blksize=0;
1.166 + return KErrNone;
1.167 + }
1.168 +
1.169 +void CFileDescBase::Complete (TRequestStatus& aStatus, TInt aResult)
1.170 + {
1.171 + TRequestStatus* sp=&aStatus;
1.172 + User::RequestComplete(sp,aResult);
1.173 + }
1.174 +
1.175 +void CFileDescBase::Write (TDes8& /*aBuf*/, TRequestStatus& aStatus)
1.176 + {
1.177 + // minimal implementation for /dev/null
1.178 + // we will claim to have written all of the data
1.179 + Complete(aStatus,KErrNone);
1.180 + }
1.181 +
1.182 +void CFileDescBase::WriteCancel() {}
1.183 +
1.184 +TInt CFileDescBase::WriteCompletion (TDes8& /*aBuf*/, TInt aStatus)
1.185 + {
1.186 + return aStatus;
1.187 + }
1.188 +
1.189 +void CFileDescBase::Sync (TRequestStatus& aStatus)
1.190 + {
1.191 + // minimal implementation for /dev/null
1.192 + Complete(aStatus,KErrNone);
1.193 + }
1.194 +
1.195 +void CFileDescBase::SyncCancel() {}
1.196 +
1.197 +void CFileDescBase::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus)
1.198 + {
1.199 + // minimal implementation for /dev/null and other synchronous devices
1.200 + Complete(aStatus,KErrNone);
1.201 + }
1.202 +
1.203 +void CFileDescBase::IoctlCancel()
1.204 + {
1.205 + return; // suitable for all synchronous ioctls
1.206 + }
1.207 +
1.208 +TInt CFileDescBase::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
1.209 + {
1.210 + TInt ret=aStatus;
1.211 + if (ret!=KErrNone)
1.212 + return ret;
1.213 + int *param=REINTERPRET_CAST(int*,aParam);
1.214 + switch (aCmd)
1.215 + {
1.216 + case E32IONREAD:
1.217 + *param=0; // claim that no data is available
1.218 + break;
1.219 + case E32IOSELECT:
1.220 + *param=(*param)&(E32SELECT_READ|E32SELECT_WRITE); // but don't block
1.221 + break;
1.222 + default:
1.223 + ret=KErrNotSupported;
1.224 + break;
1.225 + }
1.226 + return ret;
1.227 + }
1.228 +
1.229 +// A CFileDescBase factory function, for socket objects
1.230 +
1.231 +CFileDescBase* CFileDescBase::Socket(RSocketServ& aSs, int family, int style, int protocol, TInt& err)
1.232 + {
1.233 + // connect to the Socket Server if necessary
1.234 + if (aSs.Handle()==0)
1.235 + {
1.236 + err=aSs.Connect(TUint(-1)); // allow arbitrary number of requests
1.237 + if (err)
1.238 + return 0;
1.239 + }
1.240 + CSocketDesc* s= new CSocketDesc;
1.241 + if (s==0)
1.242 + {
1.243 + err=KErrNoMemory;
1.244 + return 0;
1.245 + }
1.246 + err=s->Socket(aSs,family,style,protocol);
1.247 + if (err)
1.248 + {
1.249 + delete s;
1.250 + return 0;
1.251 + }
1.252 + return s;
1.253 + }
1.254 +
1.255 +// minimal implementation of sockets, useful for all non-socket descriptors
1.256 +
1.257 +void CFileDescBase::RecvFrom(TDes8& /*aDesc*/, TSockAddr& /*from*/, int /*flags*/, TRequestStatus& aStatus)
1.258 + {
1.259 + // minimal implementation
1.260 + Complete(aStatus,ENOTSOCK);
1.261 + }
1.262 +
1.263 +void CFileDescBase::RecvFromCancel () {}
1.264 +
1.265 +TInt CFileDescBase::RecvFromCompletion(TInt& /*aLength*/, TInt aStatus)
1.266 + {
1.267 + return aStatus;
1.268 + }
1.269 +
1.270 +void CFileDescBase::SendTo(TDes8& /*aDesc*/, TSockAddr& /*to*/, int /*flags*/, TRequestStatus& aStatus)
1.271 + {
1.272 + // minimal implementation
1.273 + Complete(aStatus,ENOTSOCK);
1.274 + }
1.275 +
1.276 +void CFileDescBase::SendToCancel () {}
1.277 +
1.278 +TInt CFileDescBase::SendToCompletion(TDes8& /*aDesc*/, TInt aStatus)
1.279 + {
1.280 + return aStatus;
1.281 + }
1.282 +
1.283 +void CFileDescBase::Shutdown(TUint /*aHow*/,TRequestStatus& aStatus)
1.284 + {
1.285 + // minimal implementation
1.286 + Complete(aStatus,ENOTSOCK);
1.287 + }
1.288 +
1.289 +void CFileDescBase::ShutdownCancel () {}
1.290 +
1.291 +TInt CFileDescBase::Bind(TSockAddr& /*anAddr*/)
1.292 + {
1.293 + return ENOTSOCK;
1.294 + }
1.295 +
1.296 +TInt CFileDescBase::Listen(TUint /*qSize*/)
1.297 + {
1.298 + return ENOTSOCK;
1.299 + }
1.300 +
1.301 +void CFileDescBase::Accept(CSocketDesc*& /*aNewSocket*/, TRequestStatus& aStatus, RSocketServ& /*aSs*/)
1.302 + {
1.303 + // minimal implementation
1.304 + Complete(aStatus,ENOTSOCK);
1.305 + }
1.306 +
1.307 +void CFileDescBase::AcceptCancel () {}
1.308 +
1.309 +void CFileDescBase::Connect(TSockAddr& /*anAddr*/,TRequestStatus& aStatus)
1.310 + {
1.311 + // minimal implementation
1.312 + Complete(aStatus,ENOTSOCK);
1.313 + }
1.314 +
1.315 +void CFileDescBase::ConnectCancel () {}
1.316 +
1.317 +TInt CFileDescBase::SockName(int /*anEnd*/, TSockAddr& /*anAddr*/)
1.318 + {
1.319 + return ENOTSOCK;
1.320 + }
1.321 +
1.322 +TInt CFileDescBase::GetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDes8& /*anOption*/)
1.323 + {
1.324 + return ENOTSOCK;
1.325 + }
1.326 +
1.327 +TInt CFileDescBase::SetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDesC8& /*anOption*/)
1.328 + {
1.329 + return ENOTSOCK;
1.330 + }
1.331 +
1.332 +// Queue handling
1.333 +
1.334 +void CFileDescBase::AddLast(CPosixRequest& aRequest, IOQueues aQueue)
1.335 + {
1.336 + TPosixRequestQueue& queue = iQueues[aQueue];
1.337 + queue.AddLast(aRequest);
1.338 + if (queue.IsFirst(&aRequest))
1.339 + aRequest.StartAsynch(); // queue was empty, so start straight away
1.340 + }
1.341 +
1.342 +void CFileDescBase::Remove(CPosixRequest& aRequest, IOQueues aQueue)
1.343 + {
1.344 + TPosixRequestQueue& queue = iQueues[aQueue];
1.345 + TBool wasFirst = queue.IsFirst(&aRequest);
1.346 + queue.Remove(aRequest);
1.347 + if (wasFirst)
1.348 + {
1.349 + if (!queue.IsEmpty())
1.350 + queue.First()->StartAsynch(); // start the next outstanding request
1.351 + }
1.352 + }
1.353 +
1.354 +
1.355 +// Generic (non-virtual) handling for Close
1.356 +
1.357 +TInt CFileDescBase::Close()
1.358 + {
1.359 + TInt err=KErrNone;
1.360 + if (--iDupCount < 0)
1.361 + {
1.362 + err=FinalClose();
1.363 + delete this;
1.364 + }
1.365 + return err;
1.366 + }
1.367 +
1.368 +TInt CFileDescBase::FinalClose()
1.369 + {
1.370 + return KErrNone;
1.371 + }
1.372 +
1.373 +
1.374 +// Simple implementation of File handling
1.375 +
1.376 +static int MapMode(int aMode, TUint& fMode)
1.377 + {
1.378 + // EPOC32 doesn't support Write-Only
1.379 +
1.380 + if (aMode & (O_WRONLY|O_RDWR))
1.381 + {
1.382 + fMode = EFileWrite;
1.383 + fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareAny;
1.384 + }
1.385 + else
1.386 + {
1.387 + fMode = EFileRead;
1.388 + fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareReadersOnly;
1.389 + }
1.390 +
1.391 + fMode |= (aMode & O_TEXT) ? EFileStreamText : EFileStream;
1.392 +
1.393 + return aMode & (O_CREAT|O_TRUNC|O_APPEND|O_EXCL);
1.394 + }
1.395 +
1.396 +CFileDesc::CFileDesc()
1.397 + :CFileDescBase(), iSize(EBufferSize), iExt(-1)
1.398 + {}
1.399 +
1.400 +CFileDesc::~CFileDesc()
1.401 + {
1.402 + iFile.Close();
1.403 + delete [] iBuffer;
1.404 + }
1.405 +
1.406 +TInt CFileDesc::FinalClose()
1.407 + {
1.408 + return DoSync();
1.409 + }
1.410 +
1.411 +TInt CFileDesc::Open(RFs& aSession, const TDesC& aName, int mode, int /*perms*/)
1.412 + {
1.413 + TInt err;
1.414 + TUint fMode;
1.415 +
1.416 + iDrive=(TInt16)TDriveUnit(aName);
1.417 +
1.418 + // Create = make new file, can return KErrAlreadyExists
1.419 + // Open = open an existing file, can return KErrPathNotFound or KErrNotFound
1.420 + // Replace = open a new file, zapping the existing one if necessary
1.421 +
1.422 + int mapped=MapMode(mode, fMode);
1.423 + switch (mapped)
1.424 + {
1.425 + case O_CREAT|O_EXCL:
1.426 + err = iFile.Create(aSession, aName, fMode);
1.427 + break;
1.428 + case O_CREAT|O_TRUNC:
1.429 + err = iFile.Replace(aSession, aName, fMode);
1.430 + break;
1.431 + case O_TRUNC:
1.432 + err = iFile.Open(aSession, aName, fMode);
1.433 + if (err == KErrPathNotFound)
1.434 + {
1.435 + // missing directories etc, so fail directly
1.436 + }
1.437 + else
1.438 + {
1.439 + iFile.Close();
1.440 + err = iFile.Replace(aSession, aName, fMode);
1.441 + }
1.442 + break;
1.443 +
1.444 + // Everything else is assumed to mean open existing file,
1.445 + // If the file isn't there, O_CREAT implies that we should make it
1.446 + default:
1.447 + err = iFile.Open(aSession, aName, fMode);
1.448 + if (err == KErrNotFound && (mapped & O_CREAT))
1.449 + err = iFile.Create(aSession, aName, fMode);
1.450 + if (err == KErrNone && (mapped & O_APPEND))
1.451 + {
1.452 + iPos = Ext();
1.453 + if (iPos < 0)
1.454 + err = iPos;
1.455 + }
1.456 + break;
1.457 + }
1.458 + if ((mode & O_BUFFERED) == 0)
1.459 + iSize = 0;
1.460 + return err;
1.461 + }
1.462 +
1.463 +TInt CFileDesc::LSeek (int& offset, int whence)
1.464 + {
1.465 +
1.466 + TInt pos=offset;
1.467 + TInt ext=Ext();
1.468 + if (ext < 0)
1.469 + return ext;
1.470 +
1.471 + switch (whence)
1.472 + {
1.473 + case SEEK_SET:
1.474 + break;
1.475 + case SEEK_CUR:
1.476 + pos += Pos();
1.477 + break;
1.478 + case SEEK_END:
1.479 + pos += ext;
1.480 + break;
1.481 + default:
1.482 + return KErrArgument;
1.483 + }
1.484 + TInt ret = KErrNone;
1.485 + if (pos < 0)
1.486 + {
1.487 + pos = 0;
1.488 + ret = KErrEof;
1.489 + }
1.490 + else if (pos > ext)
1.491 + {
1.492 + pos = ext;
1.493 + ret = KErrEof;
1.494 + }
1.495 +
1.496 + switch (iState)
1.497 + {
1.498 + case EAlloc:
1.499 + iPos = pos;
1.500 + break;
1.501 + case EReading:
1.502 + {
1.503 + TInt lag = iPos - pos;
1.504 + if (lag >= 0 && lag <= (iEnd - iBuffer))
1.505 + iPtr = iEnd - lag;
1.506 + else
1.507 + {
1.508 + iPtr = iEnd;
1.509 + iPos = pos;
1.510 + }
1.511 + }
1.512 + break;
1.513 + case EWriting:
1.514 + if (pos != Pos())
1.515 + {
1.516 + ret = Flush();
1.517 + if (ret == KErrNone)
1.518 + iPos = pos;
1.519 + }
1.520 + break;
1.521 + }
1.522 + offset = pos;
1.523 + return ret;
1.524 + }
1.525 +
1.526 +void CFileDesc::MapStat(struct stat& st, const TTime& aModTime, TUint& aAttr)
1.527 + {
1.528 + st.st_mode = (aAttr&KEntryAttDir) ? S_IFDIR:S_IFREG;
1.529 + if ((aAttr&KEntryAttReadOnly)==0)
1.530 + st.st_mode |= S_IWUSR;
1.531 + st.st_nlink = 1;
1.532 + st.st_mtime = as_time_t(aModTime);
1.533 + st.st_blksize=512;
1.534 + }
1.535 +
1.536 +TInt CFileDesc::FStat (struct stat* st)
1.537 + {
1.538 + TInt err;
1.539 + TUint att;
1.540 + TTime modtime;
1.541 +
1.542 + err = iFile.Att(att);
1.543 + if (!err)
1.544 + {
1.545 + err = iFile.Modified(modtime);
1.546 + if (!err)
1.547 + {
1.548 + err=Ext();
1.549 + if (err >= 0)
1.550 + {
1.551 + st->st_size = err;
1.552 + st->st_dev = st->st_rdev = iDrive;
1.553 + MapStat(*st, modtime, att);
1.554 + return 0;
1.555 + }
1.556 + }
1.557 + }
1.558 + return err;
1.559 + }
1.560 +
1.561 +TInt CFileDesc::Alloc()
1.562 + {
1.563 + if (iSize)
1.564 + {
1.565 + iBuffer = new TUint8[iSize];
1.566 + if (iBuffer == 0)
1.567 + return KErrNoMemory;
1.568 + }
1.569 + return KErrNone;
1.570 + }
1.571 +
1.572 +TInt CFileDesc::FileRead(TUint8* aPtr,TInt aLength)
1.573 + {
1.574 + TPtr8 ptr(aPtr,aLength);
1.575 + TInt r=iFile.Read(iPos,ptr);
1.576 + if (r == KErrNone)
1.577 + {
1.578 + r = ptr.Length();
1.579 + iPos += r;
1.580 + if (r < aLength)
1.581 + iExt = iPos;
1.582 + }
1.583 + return r;
1.584 + }
1.585 +
1.586 +TInt CFileDesc::FileWrite(TUint8* aPtr,TInt aLength)
1.587 + {
1.588 + TPtrC8 ptr(aPtr,aLength);
1.589 + TInt r = iFile.Write(iPos,ptr);
1.590 + if (r == KErrNone)
1.591 + {
1.592 + iPos += aLength;
1.593 + if (iPos > iExt && iExt >= 0)
1.594 + iExt = iPos;
1.595 + }
1.596 + return r;
1.597 + }
1.598 +
1.599 +TInt CFileDesc::Flush()
1.600 + {
1.601 + if (iPtr > iBuffer)
1.602 + {
1.603 + TInt r = FileWrite(iBuffer, iPtr-iBuffer);
1.604 + if (r < 0)
1.605 + return r;
1.606 + iPtr = iBuffer;
1.607 + }
1.608 + return KErrNone;
1.609 + }
1.610 +
1.611 +TInt CFileDesc::DoRead (TDes8& aDesc)
1.612 + {
1.613 + if (iState != EReading)
1.614 + {
1.615 + TInt ret = (iState == EAlloc) ? Alloc() : Flush();
1.616 + if (ret != KErrNone)
1.617 + return ret;
1.618 + iState = EReading;
1.619 + iPtr = iEnd = iBuffer;
1.620 + }
1.621 +
1.622 + TUint8* p = (TUint8*) aDesc.Ptr();
1.623 + TInt max = aDesc.MaxLength();
1.624 + TInt avail = iEnd - iPtr;
1.625 + TInt len = Min(max, avail);
1.626 + if (len > 0)
1.627 + {
1.628 + p = Mem::Copy(p, iPtr, len);
1.629 + iPtr += len;
1.630 + max -= len;
1.631 + }
1.632 + if (max >= iSize)
1.633 + {
1.634 + TInt ret = FileRead(p, max);
1.635 + if (ret < 0)
1.636 + return ret;
1.637 + p += ret;
1.638 + }
1.639 + else if (max > 0)
1.640 + {
1.641 + TInt ret = FileRead(iBuffer, Min(max + EReadAhead, iSize));
1.642 + if (ret < 0)
1.643 + return ret;
1.644 + len = Min(max, ret);
1.645 + p = Mem::Copy(p, iBuffer, len);
1.646 + iPtr = iBuffer + len;
1.647 + iEnd = iBuffer + ret;
1.648 + }
1.649 + aDesc.SetLength(p-aDesc.Ptr());
1.650 + return KErrNone;
1.651 + }
1.652 +
1.653 +void CFileDesc::Read (TDes8& aDesc, TRequestStatus& aStatus)
1.654 + {
1.655 + Complete(aStatus,DoRead(aDesc));
1.656 + }
1.657 +
1.658 +TInt CFileDesc::DoWrite (TDes8& aDesc)
1.659 + {
1.660 + if (iState != EWriting)
1.661 + {
1.662 + if (iState == EAlloc)
1.663 + {
1.664 + TInt ret = Alloc();
1.665 + if (ret != KErrNone)
1.666 + return ret;
1.667 + }
1.668 + else
1.669 + iPos -= iEnd - iPtr;
1.670 +
1.671 + iState = EWriting;
1.672 + iPtr = iBuffer;
1.673 + iEnd = iBuffer + iSize;
1.674 + }
1.675 +
1.676 + TUint8* p = (TUint8*) aDesc.Ptr();
1.677 + TInt max = aDesc.Length();
1.678 + TInt avail = iEnd - iPtr;
1.679 + TInt len = Min(max, avail);
1.680 + if (len > 0)
1.681 + {
1.682 + iPtr = Mem::Copy(iPtr, p, len);
1.683 + p += len;
1.684 + max -= len;
1.685 + }
1.686 + if (max == 0)
1.687 + return KErrNone;
1.688 + TInt r=Flush();
1.689 + if (r < 0)
1.690 + return r;
1.691 + if (max >= iSize)
1.692 + return FileWrite(p, max);
1.693 + iPtr = Mem::Copy(iPtr, p, max);
1.694 + return KErrNone;
1.695 + }
1.696 +
1.697 +void CFileDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
1.698 + {
1.699 + Complete(aStatus,DoWrite(aDesc));
1.700 + }
1.701 +
1.702 +TInt CFileDesc::DoSync()
1.703 + {
1.704 + if (iState == EWriting)
1.705 + {
1.706 + TInt ret = Flush();
1.707 + if (ret < 0)
1.708 + return ret;
1.709 + }
1.710 + return iFile.Flush();
1.711 + }
1.712 +
1.713 +void CFileDesc::Sync(TRequestStatus& aStatus)
1.714 + {
1.715 + Complete(aStatus,DoSync());
1.716 + }
1.717 +
1.718 +TInt CFileDesc::Pos()
1.719 + {
1.720 + TInt pos = iPos;
1.721 + if (iState == EReading)
1.722 + pos -= (iEnd - iPtr);
1.723 + else if (iState == EWriting)
1.724 + pos += (iPtr - iBuffer);
1.725 + return pos;
1.726 + }
1.727 +
1.728 +TInt CFileDesc::Ext()
1.729 + {
1.730 + if (iExt < 0)
1.731 + {
1.732 + TInt r = iFile.Size(iExt);
1.733 + if (r < 0)
1.734 + return r;
1.735 + }
1.736 + return Max(iExt, Pos());
1.737 + }
1.738 +
1.739 +TInt CFileDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
1.740 + {
1.741 + TInt ret=aStatus;
1.742 + if (ret!=KErrNone)
1.743 + return ret;
1.744 + // some useful sums about the current state of the file
1.745 + TInt curoff = Pos();
1.746 + TInt size = Ext();
1.747 + if (size < 0)
1.748 + ret = size;
1.749 + int *param=REINTERPRET_CAST(int*,aParam);
1.750 + switch (aCmd)
1.751 + {
1.752 + case E32IONREAD:
1.753 + if (ret==KErrNone)
1.754 + *param=(size-curoff);
1.755 + break;
1.756 + case E32IOSELECT:
1.757 + {
1.758 + int mask=E32SELECT_WRITE;
1.759 + if ((size-curoff)>0)
1.760 + mask |= E32SELECT_READ;
1.761 + *param=(*param)&mask; // but don't block
1.762 + }
1.763 + break;
1.764 + default:
1.765 + ret=KErrNotSupported;
1.766 + break;
1.767 + }
1.768 + return ret;
1.769 + }
1.770 +
1.771 +// Extra support for temporary files
1.772 +
1.773 +TInt CTempFileDesc::Open(RFs& aSession, const TDesC& aPath)
1.774 + {
1.775 + iSession=aSession;
1.776 + iDrive=(TInt16)TDriveUnit(aPath);
1.777 + TInt err=iFile.Temp(aSession, aPath, iName, EFileShareAny);
1.778 + return err;
1.779 + }
1.780 +
1.781 +TInt CTempFileDesc::FinalClose()
1.782 + {
1.783 + iFile.Close();
1.784 + TInt err=iSession.Delete(iName);
1.785 + return err;
1.786 + }