sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "FDESC.H" sl@0: #include "LPOSIX.H" sl@0: #include "LTIME.H" sl@0: #include sl@0: #include sl@0: #include // for struct stat sl@0: #include // for ENOTSOCK sl@0: #include sl@0: #include sl@0: sl@0: #include "POSIXIF.H" // for details of CPosixRequest::iLink sl@0: sl@0: // Cleanup support sl@0: sl@0: void CFileDescBase::Cleanup(TAny *aPtr) sl@0: { sl@0: ((CFileDescBase*)aPtr)->Close(); sl@0: } sl@0: sl@0: void CFileDescBase::PushLC() sl@0: { sl@0: CleanupStack::PushL(TCleanupItem(Cleanup,this)); sl@0: } sl@0: sl@0: // Private constructor sl@0: sl@0: inline TPosixRequestQueue::TPosixRequestQueue() sl@0: : TSglQue(_FOFF(CPosixRequest,iLink)) sl@0: {} sl@0: sl@0: CFileDescBase::CFileDescBase() : iReadTimeout(-1) sl@0: { sl@0: } sl@0: sl@0: // A CFileDescBase factory function, for "named" file-like objects sl@0: sl@0: //CFileDescBase* CFileDescBase::Open(RFs& aSession, const char* name, int mode, int perms, TInt& err) sl@0: //CFileDescBase* CFileDescBase::Open(RFs& aSession, const wchar_t* name, int mode, int perms, TInt& err) sl@0: CFileDescBase* CFileDescBase::Open(RSessionBase& aSession, const wchar_t* name, int mode, int perms, TInt& err) sl@0: { sl@0: CFileDescBase* ret=0; sl@0: sl@0: if (wcscmp(name,L"CON:")==0) sl@0: ret= new CTtyDesc; // NB. This won't be the default stdin/stdout/stderr console sl@0: else sl@0: if (wcscmp(name,L"NUL:")==0) sl@0: ret= new CFileDescBase; sl@0: else sl@0: if (wcscmp(name,L"TMP:")==0) sl@0: { sl@0: RFs& rfs = static_cast(aSession); sl@0: TParse path; sl@0: err=GetFullPath(path,(const TText16*)WIDEP_tmpdir, rfs,NULL); sl@0: if (err) sl@0: return 0; sl@0: CTempFileDesc* tmp= new CTempFileDesc; sl@0: if (tmp) sl@0: { sl@0: err=tmp->Open(rfs,path.DriveAndPath()); sl@0: if (err) sl@0: { sl@0: delete tmp; sl@0: return 0; sl@0: } sl@0: } sl@0: ret=tmp; sl@0: } sl@0: 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')) || sl@0: (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'))) sl@0: { sl@0: sl@0: RCommServ& rcs = static_cast(aSession); sl@0: if (!rcs.Handle()) sl@0: { sl@0: err=rcs.Connect(); //connect to the server sl@0: if (err) sl@0: return 0; sl@0: } sl@0: CSerialDesc * tmp = new CSerialDesc; sl@0: if (tmp) sl@0: { sl@0: RCommServ& rcs = static_cast(aSession); sl@0: CleanupStack::PushL(tmp); sl@0: err = tmp->Open(rcs, name, mode, perms); sl@0: CleanupStack::Pop(tmp); sl@0: if (err) sl@0: { sl@0: delete tmp; sl@0: return 0; sl@0: } sl@0: } sl@0: ret = tmp; sl@0: } sl@0: else sl@0: { sl@0: TFullName fullName; sl@0: RFs& rfs = static_cast(aSession); sl@0: err=GetFullFile(fullName,(const TText16*)name,rfs); sl@0: if (err) sl@0: return 0; sl@0: CFileDesc* f= new CFileDesc; sl@0: if (f) sl@0: { sl@0: err=f->Open(rfs,fullName,mode,perms); sl@0: if (err) sl@0: { sl@0: delete f; sl@0: return 0; sl@0: } sl@0: } sl@0: ret=f; sl@0: } sl@0: err=(ret==0)? KErrNoMemory:KErrNone; sl@0: return ret; sl@0: } sl@0: sl@0: // Useful default implementations for CFileDescBase virtual functions. sl@0: sl@0: TInt CFileDescBase::LSeek (int& offset, int) sl@0: { sl@0: // minimal implementation for devices which can't seek sl@0: offset=0; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CFileDescBase::Read (TDes8& aBuf, TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation for /dev/null sl@0: aBuf.Zero(); // set length to zero sl@0: TRequestStatus* sp=&aStatus; sl@0: User::RequestComplete(sp,KErrNone); sl@0: } sl@0: sl@0: void CFileDescBase::ReadCancel() {} sl@0: sl@0: TInt CFileDescBase::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus) sl@0: { sl@0: return aStatus; sl@0: } sl@0: sl@0: sl@0: TInt CFileDescBase::FStat (struct stat *st) sl@0: { sl@0: // minimal implementation: sl@0: // I am a character device about which little is known sl@0: st->st_mode = S_IFCHR; sl@0: st->st_blksize=0; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CFileDescBase::Complete (TRequestStatus& aStatus, TInt aResult) sl@0: { sl@0: TRequestStatus* sp=&aStatus; sl@0: User::RequestComplete(sp,aResult); sl@0: } sl@0: sl@0: void CFileDescBase::Write (TDes8& /*aBuf*/, TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation for /dev/null sl@0: // we will claim to have written all of the data sl@0: Complete(aStatus,KErrNone); sl@0: } sl@0: sl@0: void CFileDescBase::WriteCancel() {} sl@0: sl@0: TInt CFileDescBase::WriteCompletion (TDes8& /*aBuf*/, TInt aStatus) sl@0: { sl@0: return aStatus; sl@0: } sl@0: sl@0: void CFileDescBase::Sync (TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation for /dev/null sl@0: Complete(aStatus,KErrNone); sl@0: } sl@0: sl@0: void CFileDescBase::SyncCancel() {} sl@0: sl@0: void CFileDescBase::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation for /dev/null and other synchronous devices sl@0: Complete(aStatus,KErrNone); sl@0: } sl@0: sl@0: void CFileDescBase::IoctlCancel() sl@0: { sl@0: return; // suitable for all synchronous ioctls sl@0: } sl@0: sl@0: TInt CFileDescBase::IoctlCompletion(int aCmd, void* aParam, TInt aStatus) sl@0: { sl@0: TInt ret=aStatus; sl@0: if (ret!=KErrNone) sl@0: return ret; sl@0: int *param=REINTERPRET_CAST(int*,aParam); sl@0: switch (aCmd) sl@0: { sl@0: case E32IONREAD: sl@0: *param=0; // claim that no data is available sl@0: break; sl@0: case E32IOSELECT: sl@0: *param=(*param)&(E32SELECT_READ|E32SELECT_WRITE); // but don't block sl@0: break; sl@0: default: sl@0: ret=KErrNotSupported; sl@0: break; sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: // A CFileDescBase factory function, for socket objects sl@0: sl@0: CFileDescBase* CFileDescBase::Socket(RSocketServ& aSs, int family, int style, int protocol, TInt& err) sl@0: { sl@0: // connect to the Socket Server if necessary sl@0: if (aSs.Handle()==0) sl@0: { sl@0: err=aSs.Connect(TUint(-1)); // allow arbitrary number of requests sl@0: if (err) sl@0: return 0; sl@0: } sl@0: CSocketDesc* s= new CSocketDesc; sl@0: if (s==0) sl@0: { sl@0: err=KErrNoMemory; sl@0: return 0; sl@0: } sl@0: err=s->Socket(aSs,family,style,protocol); sl@0: if (err) sl@0: { sl@0: delete s; sl@0: return 0; sl@0: } sl@0: return s; sl@0: } sl@0: sl@0: // minimal implementation of sockets, useful for all non-socket descriptors sl@0: sl@0: void CFileDescBase::RecvFrom(TDes8& /*aDesc*/, TSockAddr& /*from*/, int /*flags*/, TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation sl@0: Complete(aStatus,ENOTSOCK); sl@0: } sl@0: sl@0: void CFileDescBase::RecvFromCancel () {} sl@0: sl@0: TInt CFileDescBase::RecvFromCompletion(TInt& /*aLength*/, TInt aStatus) sl@0: { sl@0: return aStatus; sl@0: } sl@0: sl@0: void CFileDescBase::SendTo(TDes8& /*aDesc*/, TSockAddr& /*to*/, int /*flags*/, TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation sl@0: Complete(aStatus,ENOTSOCK); sl@0: } sl@0: sl@0: void CFileDescBase::SendToCancel () {} sl@0: sl@0: TInt CFileDescBase::SendToCompletion(TDes8& /*aDesc*/, TInt aStatus) sl@0: { sl@0: return aStatus; sl@0: } sl@0: sl@0: void CFileDescBase::Shutdown(TUint /*aHow*/,TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation sl@0: Complete(aStatus,ENOTSOCK); sl@0: } sl@0: sl@0: void CFileDescBase::ShutdownCancel () {} sl@0: sl@0: TInt CFileDescBase::Bind(TSockAddr& /*anAddr*/) sl@0: { sl@0: return ENOTSOCK; sl@0: } sl@0: sl@0: TInt CFileDescBase::Listen(TUint /*qSize*/) sl@0: { sl@0: return ENOTSOCK; sl@0: } sl@0: sl@0: void CFileDescBase::Accept(CSocketDesc*& /*aNewSocket*/, TRequestStatus& aStatus, RSocketServ& /*aSs*/) sl@0: { sl@0: // minimal implementation sl@0: Complete(aStatus,ENOTSOCK); sl@0: } sl@0: sl@0: void CFileDescBase::AcceptCancel () {} sl@0: sl@0: void CFileDescBase::Connect(TSockAddr& /*anAddr*/,TRequestStatus& aStatus) sl@0: { sl@0: // minimal implementation sl@0: Complete(aStatus,ENOTSOCK); sl@0: } sl@0: sl@0: void CFileDescBase::ConnectCancel () {} sl@0: sl@0: TInt CFileDescBase::SockName(int /*anEnd*/, TSockAddr& /*anAddr*/) sl@0: { sl@0: return ENOTSOCK; sl@0: } sl@0: sl@0: TInt CFileDescBase::GetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDes8& /*anOption*/) sl@0: { sl@0: return ENOTSOCK; sl@0: } sl@0: sl@0: TInt CFileDescBase::SetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDesC8& /*anOption*/) sl@0: { sl@0: return ENOTSOCK; sl@0: } sl@0: sl@0: // Queue handling sl@0: sl@0: void CFileDescBase::AddLast(CPosixRequest& aRequest, IOQueues aQueue) sl@0: { sl@0: TPosixRequestQueue& queue = iQueues[aQueue]; sl@0: queue.AddLast(aRequest); sl@0: if (queue.IsFirst(&aRequest)) sl@0: aRequest.StartAsynch(); // queue was empty, so start straight away sl@0: } sl@0: sl@0: void CFileDescBase::Remove(CPosixRequest& aRequest, IOQueues aQueue) sl@0: { sl@0: TPosixRequestQueue& queue = iQueues[aQueue]; sl@0: TBool wasFirst = queue.IsFirst(&aRequest); sl@0: queue.Remove(aRequest); sl@0: if (wasFirst) sl@0: { sl@0: if (!queue.IsEmpty()) sl@0: queue.First()->StartAsynch(); // start the next outstanding request sl@0: } sl@0: } sl@0: sl@0: sl@0: // Generic (non-virtual) handling for Close sl@0: sl@0: TInt CFileDescBase::Close() sl@0: { sl@0: TInt err=KErrNone; sl@0: if (--iDupCount < 0) sl@0: { sl@0: err=FinalClose(); sl@0: delete this; sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: TInt CFileDescBase::FinalClose() sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: // Simple implementation of File handling sl@0: sl@0: static int MapMode(int aMode, TUint& fMode) sl@0: { sl@0: // EPOC32 doesn't support Write-Only sl@0: sl@0: if (aMode & (O_WRONLY|O_RDWR)) sl@0: { sl@0: fMode = EFileWrite; sl@0: fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareAny; sl@0: } sl@0: else sl@0: { sl@0: fMode = EFileRead; sl@0: fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareReadersOnly; sl@0: } sl@0: sl@0: fMode |= (aMode & O_TEXT) ? EFileStreamText : EFileStream; sl@0: sl@0: return aMode & (O_CREAT|O_TRUNC|O_APPEND|O_EXCL); sl@0: } sl@0: sl@0: CFileDesc::CFileDesc() sl@0: :CFileDescBase(), iSize(EBufferSize), iExt(-1) sl@0: {} sl@0: sl@0: CFileDesc::~CFileDesc() sl@0: { sl@0: iFile.Close(); sl@0: delete [] iBuffer; sl@0: } sl@0: sl@0: TInt CFileDesc::FinalClose() sl@0: { sl@0: return DoSync(); sl@0: } sl@0: sl@0: TInt CFileDesc::Open(RFs& aSession, const TDesC& aName, int mode, int /*perms*/) sl@0: { sl@0: TInt err; sl@0: TUint fMode; sl@0: sl@0: iDrive=(TInt16)TDriveUnit(aName); sl@0: sl@0: // Create = make new file, can return KErrAlreadyExists sl@0: // Open = open an existing file, can return KErrPathNotFound or KErrNotFound sl@0: // Replace = open a new file, zapping the existing one if necessary sl@0: sl@0: int mapped=MapMode(mode, fMode); sl@0: switch (mapped) sl@0: { sl@0: case O_CREAT|O_EXCL: sl@0: err = iFile.Create(aSession, aName, fMode); sl@0: break; sl@0: case O_CREAT|O_TRUNC: sl@0: err = iFile.Replace(aSession, aName, fMode); sl@0: break; sl@0: case O_TRUNC: sl@0: err = iFile.Open(aSession, aName, fMode); sl@0: if (err == KErrPathNotFound) sl@0: { sl@0: // missing directories etc, so fail directly sl@0: } sl@0: else sl@0: { sl@0: iFile.Close(); sl@0: err = iFile.Replace(aSession, aName, fMode); sl@0: } sl@0: break; sl@0: sl@0: // Everything else is assumed to mean open existing file, sl@0: // If the file isn't there, O_CREAT implies that we should make it sl@0: default: sl@0: err = iFile.Open(aSession, aName, fMode); sl@0: if (err == KErrNotFound && (mapped & O_CREAT)) sl@0: err = iFile.Create(aSession, aName, fMode); sl@0: if (err == KErrNone && (mapped & O_APPEND)) sl@0: { sl@0: iPos = Ext(); sl@0: if (iPos < 0) sl@0: err = iPos; sl@0: } sl@0: break; sl@0: } sl@0: if ((mode & O_BUFFERED) == 0) sl@0: iSize = 0; sl@0: return err; sl@0: } sl@0: sl@0: TInt CFileDesc::LSeek (int& offset, int whence) sl@0: { sl@0: sl@0: TInt pos=offset; sl@0: TInt ext=Ext(); sl@0: if (ext < 0) sl@0: return ext; sl@0: sl@0: switch (whence) sl@0: { sl@0: case SEEK_SET: sl@0: break; sl@0: case SEEK_CUR: sl@0: pos += Pos(); sl@0: break; sl@0: case SEEK_END: sl@0: pos += ext; sl@0: break; sl@0: default: sl@0: return KErrArgument; sl@0: } sl@0: TInt ret = KErrNone; sl@0: if (pos < 0) sl@0: { sl@0: pos = 0; sl@0: ret = KErrEof; sl@0: } sl@0: else if (pos > ext) sl@0: { sl@0: pos = ext; sl@0: ret = KErrEof; sl@0: } sl@0: sl@0: switch (iState) sl@0: { sl@0: case EAlloc: sl@0: iPos = pos; sl@0: break; sl@0: case EReading: sl@0: { sl@0: TInt lag = iPos - pos; sl@0: if (lag >= 0 && lag <= (iEnd - iBuffer)) sl@0: iPtr = iEnd - lag; sl@0: else sl@0: { sl@0: iPtr = iEnd; sl@0: iPos = pos; sl@0: } sl@0: } sl@0: break; sl@0: case EWriting: sl@0: if (pos != Pos()) sl@0: { sl@0: ret = Flush(); sl@0: if (ret == KErrNone) sl@0: iPos = pos; sl@0: } sl@0: break; sl@0: } sl@0: offset = pos; sl@0: return ret; sl@0: } sl@0: sl@0: void CFileDesc::MapStat(struct stat& st, const TTime& aModTime, TUint& aAttr) sl@0: { sl@0: st.st_mode = (aAttr&KEntryAttDir) ? S_IFDIR:S_IFREG; sl@0: if ((aAttr&KEntryAttReadOnly)==0) sl@0: st.st_mode |= S_IWUSR; sl@0: st.st_nlink = 1; sl@0: st.st_mtime = as_time_t(aModTime); sl@0: st.st_blksize=512; sl@0: } sl@0: sl@0: TInt CFileDesc::FStat (struct stat* st) sl@0: { sl@0: TInt err; sl@0: TUint att; sl@0: TTime modtime; sl@0: sl@0: err = iFile.Att(att); sl@0: if (!err) sl@0: { sl@0: err = iFile.Modified(modtime); sl@0: if (!err) sl@0: { sl@0: err=Ext(); sl@0: if (err >= 0) sl@0: { sl@0: st->st_size = err; sl@0: st->st_dev = st->st_rdev = iDrive; sl@0: MapStat(*st, modtime, att); sl@0: return 0; sl@0: } sl@0: } sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: TInt CFileDesc::Alloc() sl@0: { sl@0: if (iSize) sl@0: { sl@0: iBuffer = new TUint8[iSize]; sl@0: if (iBuffer == 0) sl@0: return KErrNoMemory; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CFileDesc::FileRead(TUint8* aPtr,TInt aLength) sl@0: { sl@0: TPtr8 ptr(aPtr,aLength); sl@0: TInt r=iFile.Read(iPos,ptr); sl@0: if (r == KErrNone) sl@0: { sl@0: r = ptr.Length(); sl@0: iPos += r; sl@0: if (r < aLength) sl@0: iExt = iPos; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt CFileDesc::FileWrite(TUint8* aPtr,TInt aLength) sl@0: { sl@0: TPtrC8 ptr(aPtr,aLength); sl@0: TInt r = iFile.Write(iPos,ptr); sl@0: if (r == KErrNone) sl@0: { sl@0: iPos += aLength; sl@0: if (iPos > iExt && iExt >= 0) sl@0: iExt = iPos; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt CFileDesc::Flush() sl@0: { sl@0: if (iPtr > iBuffer) sl@0: { sl@0: TInt r = FileWrite(iBuffer, iPtr-iBuffer); sl@0: if (r < 0) sl@0: return r; sl@0: iPtr = iBuffer; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CFileDesc::DoRead (TDes8& aDesc) sl@0: { sl@0: if (iState != EReading) sl@0: { sl@0: TInt ret = (iState == EAlloc) ? Alloc() : Flush(); sl@0: if (ret != KErrNone) sl@0: return ret; sl@0: iState = EReading; sl@0: iPtr = iEnd = iBuffer; sl@0: } sl@0: sl@0: TUint8* p = (TUint8*) aDesc.Ptr(); sl@0: TInt max = aDesc.MaxLength(); sl@0: TInt avail = iEnd - iPtr; sl@0: TInt len = Min(max, avail); sl@0: if (len > 0) sl@0: { sl@0: p = Mem::Copy(p, iPtr, len); sl@0: iPtr += len; sl@0: max -= len; sl@0: } sl@0: if (max >= iSize) sl@0: { sl@0: TInt ret = FileRead(p, max); sl@0: if (ret < 0) sl@0: return ret; sl@0: p += ret; sl@0: } sl@0: else if (max > 0) sl@0: { sl@0: TInt ret = FileRead(iBuffer, Min(max + EReadAhead, iSize)); sl@0: if (ret < 0) sl@0: return ret; sl@0: len = Min(max, ret); sl@0: p = Mem::Copy(p, iBuffer, len); sl@0: iPtr = iBuffer + len; sl@0: iEnd = iBuffer + ret; sl@0: } sl@0: aDesc.SetLength(p-aDesc.Ptr()); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CFileDesc::Read (TDes8& aDesc, TRequestStatus& aStatus) sl@0: { sl@0: Complete(aStatus,DoRead(aDesc)); sl@0: } sl@0: sl@0: TInt CFileDesc::DoWrite (TDes8& aDesc) sl@0: { sl@0: if (iState != EWriting) sl@0: { sl@0: if (iState == EAlloc) sl@0: { sl@0: TInt ret = Alloc(); sl@0: if (ret != KErrNone) sl@0: return ret; sl@0: } sl@0: else sl@0: iPos -= iEnd - iPtr; sl@0: sl@0: iState = EWriting; sl@0: iPtr = iBuffer; sl@0: iEnd = iBuffer + iSize; sl@0: } sl@0: sl@0: TUint8* p = (TUint8*) aDesc.Ptr(); sl@0: TInt max = aDesc.Length(); sl@0: TInt avail = iEnd - iPtr; sl@0: TInt len = Min(max, avail); sl@0: if (len > 0) sl@0: { sl@0: iPtr = Mem::Copy(iPtr, p, len); sl@0: p += len; sl@0: max -= len; sl@0: } sl@0: if (max == 0) sl@0: return KErrNone; sl@0: TInt r=Flush(); sl@0: if (r < 0) sl@0: return r; sl@0: if (max >= iSize) sl@0: return FileWrite(p, max); sl@0: iPtr = Mem::Copy(iPtr, p, max); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CFileDesc::Write(TDes8& aDesc, TRequestStatus& aStatus) sl@0: { sl@0: Complete(aStatus,DoWrite(aDesc)); sl@0: } sl@0: sl@0: TInt CFileDesc::DoSync() sl@0: { sl@0: if (iState == EWriting) sl@0: { sl@0: TInt ret = Flush(); sl@0: if (ret < 0) sl@0: return ret; sl@0: } sl@0: return iFile.Flush(); sl@0: } sl@0: sl@0: void CFileDesc::Sync(TRequestStatus& aStatus) sl@0: { sl@0: Complete(aStatus,DoSync()); sl@0: } sl@0: sl@0: TInt CFileDesc::Pos() sl@0: { sl@0: TInt pos = iPos; sl@0: if (iState == EReading) sl@0: pos -= (iEnd - iPtr); sl@0: else if (iState == EWriting) sl@0: pos += (iPtr - iBuffer); sl@0: return pos; sl@0: } sl@0: sl@0: TInt CFileDesc::Ext() sl@0: { sl@0: if (iExt < 0) sl@0: { sl@0: TInt r = iFile.Size(iExt); sl@0: if (r < 0) sl@0: return r; sl@0: } sl@0: return Max(iExt, Pos()); sl@0: } sl@0: sl@0: TInt CFileDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus) sl@0: { sl@0: TInt ret=aStatus; sl@0: if (ret!=KErrNone) sl@0: return ret; sl@0: // some useful sums about the current state of the file sl@0: TInt curoff = Pos(); sl@0: TInt size = Ext(); sl@0: if (size < 0) sl@0: ret = size; sl@0: int *param=REINTERPRET_CAST(int*,aParam); sl@0: switch (aCmd) sl@0: { sl@0: case E32IONREAD: sl@0: if (ret==KErrNone) sl@0: *param=(size-curoff); sl@0: break; sl@0: case E32IOSELECT: sl@0: { sl@0: int mask=E32SELECT_WRITE; sl@0: if ((size-curoff)>0) sl@0: mask |= E32SELECT_READ; sl@0: *param=(*param)&mask; // but don't block sl@0: } sl@0: break; sl@0: default: sl@0: ret=KErrNotSupported; sl@0: break; sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: // Extra support for temporary files sl@0: sl@0: TInt CTempFileDesc::Open(RFs& aSession, const TDesC& aPath) sl@0: { sl@0: iSession=aSession; sl@0: iDrive=(TInt16)TDriveUnit(aPath); sl@0: TInt err=iFile.Temp(aSession, aPath, iName, EFileShareAny); sl@0: return err; sl@0: } sl@0: sl@0: TInt CTempFileDesc::FinalClose() sl@0: { sl@0: iFile.Close(); sl@0: TInt err=iSession.Delete(iName); sl@0: return err; sl@0: }