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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <fcntl.h> // for struct stat
22 #include <sys/errno.h> // for ENOTSOCK
23 #include <sys/ioctl.h>
26 #include "POSIXIF.H" // for details of CPosixRequest::iLink
30 void CFileDescBase::Cleanup(TAny *aPtr)
32 ((CFileDescBase*)aPtr)->Close();
35 void CFileDescBase::PushLC()
37 CleanupStack::PushL(TCleanupItem(Cleanup,this));
40 // Private constructor
42 inline TPosixRequestQueue::TPosixRequestQueue()
43 : TSglQue<CPosixRequest>(_FOFF(CPosixRequest,iLink))
46 CFileDescBase::CFileDescBase() : iReadTimeout(-1)
50 // A CFileDescBase factory function, for "named" file-like objects
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)
58 if (wcscmp(name,L"CON:")==0)
59 ret= new CTtyDesc; // NB. This won't be the default stdin/stdout/stderr console
61 if (wcscmp(name,L"NUL:")==0)
62 ret= new CFileDescBase;
64 if (wcscmp(name,L"TMP:")==0)
66 RFs& rfs = static_cast<RFs&>(aSession);
68 err=GetFullPath(path,(const TText16*)WIDEP_tmpdir, rfs,NULL);
71 CTempFileDesc* tmp= new CTempFileDesc;
74 err=tmp->Open(rfs,path.DriveAndPath());
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')))
87 RCommServ& rcs = static_cast<RCommServ&>(aSession);
90 err=rcs.Connect(); //connect to the server
94 CSerialDesc * tmp = new CSerialDesc;
97 RCommServ& rcs = static_cast<RCommServ&>(aSession);
98 CleanupStack::PushL(tmp);
99 err = tmp->Open(rcs, name, mode, perms);
100 CleanupStack::Pop(tmp);
112 RFs& rfs = static_cast<RFs&>(aSession);
113 err=GetFullFile(fullName,(const TText16*)name,rfs);
116 CFileDesc* f= new CFileDesc;
119 err=f->Open(rfs,fullName,mode,perms);
128 err=(ret==0)? KErrNoMemory:KErrNone;
132 // Useful default implementations for CFileDescBase virtual functions.
134 TInt CFileDescBase::LSeek (int& offset, int)
136 // minimal implementation for devices which can't seek
141 void CFileDescBase::Read (TDes8& aBuf, TRequestStatus& aStatus)
143 // minimal implementation for /dev/null
144 aBuf.Zero(); // set length to zero
145 TRequestStatus* sp=&aStatus;
146 User::RequestComplete(sp,KErrNone);
149 void CFileDescBase::ReadCancel() {}
151 TInt CFileDescBase::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus)
157 TInt CFileDescBase::FStat (struct stat *st)
159 // minimal implementation:
160 // I am a character device about which little is known
161 st->st_mode = S_IFCHR;
166 void CFileDescBase::Complete (TRequestStatus& aStatus, TInt aResult)
168 TRequestStatus* sp=&aStatus;
169 User::RequestComplete(sp,aResult);
172 void CFileDescBase::Write (TDes8& /*aBuf*/, TRequestStatus& aStatus)
174 // minimal implementation for /dev/null
175 // we will claim to have written all of the data
176 Complete(aStatus,KErrNone);
179 void CFileDescBase::WriteCancel() {}
181 TInt CFileDescBase::WriteCompletion (TDes8& /*aBuf*/, TInt aStatus)
186 void CFileDescBase::Sync (TRequestStatus& aStatus)
188 // minimal implementation for /dev/null
189 Complete(aStatus,KErrNone);
192 void CFileDescBase::SyncCancel() {}
194 void CFileDescBase::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus)
196 // minimal implementation for /dev/null and other synchronous devices
197 Complete(aStatus,KErrNone);
200 void CFileDescBase::IoctlCancel()
202 return; // suitable for all synchronous ioctls
205 TInt CFileDescBase::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
210 int *param=REINTERPRET_CAST(int*,aParam);
214 *param=0; // claim that no data is available
217 *param=(*param)&(E32SELECT_READ|E32SELECT_WRITE); // but don't block
220 ret=KErrNotSupported;
226 // A CFileDescBase factory function, for socket objects
228 CFileDescBase* CFileDescBase::Socket(RSocketServ& aSs, int family, int style, int protocol, TInt& err)
230 // connect to the Socket Server if necessary
233 err=aSs.Connect(TUint(-1)); // allow arbitrary number of requests
237 CSocketDesc* s= new CSocketDesc;
243 err=s->Socket(aSs,family,style,protocol);
252 // minimal implementation of sockets, useful for all non-socket descriptors
254 void CFileDescBase::RecvFrom(TDes8& /*aDesc*/, TSockAddr& /*from*/, int /*flags*/, TRequestStatus& aStatus)
256 // minimal implementation
257 Complete(aStatus,ENOTSOCK);
260 void CFileDescBase::RecvFromCancel () {}
262 TInt CFileDescBase::RecvFromCompletion(TInt& /*aLength*/, TInt aStatus)
267 void CFileDescBase::SendTo(TDes8& /*aDesc*/, TSockAddr& /*to*/, int /*flags*/, TRequestStatus& aStatus)
269 // minimal implementation
270 Complete(aStatus,ENOTSOCK);
273 void CFileDescBase::SendToCancel () {}
275 TInt CFileDescBase::SendToCompletion(TDes8& /*aDesc*/, TInt aStatus)
280 void CFileDescBase::Shutdown(TUint /*aHow*/,TRequestStatus& aStatus)
282 // minimal implementation
283 Complete(aStatus,ENOTSOCK);
286 void CFileDescBase::ShutdownCancel () {}
288 TInt CFileDescBase::Bind(TSockAddr& /*anAddr*/)
293 TInt CFileDescBase::Listen(TUint /*qSize*/)
298 void CFileDescBase::Accept(CSocketDesc*& /*aNewSocket*/, TRequestStatus& aStatus, RSocketServ& /*aSs*/)
300 // minimal implementation
301 Complete(aStatus,ENOTSOCK);
304 void CFileDescBase::AcceptCancel () {}
306 void CFileDescBase::Connect(TSockAddr& /*anAddr*/,TRequestStatus& aStatus)
308 // minimal implementation
309 Complete(aStatus,ENOTSOCK);
312 void CFileDescBase::ConnectCancel () {}
314 TInt CFileDescBase::SockName(int /*anEnd*/, TSockAddr& /*anAddr*/)
319 TInt CFileDescBase::GetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDes8& /*anOption*/)
324 TInt CFileDescBase::SetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDesC8& /*anOption*/)
331 void CFileDescBase::AddLast(CPosixRequest& aRequest, IOQueues aQueue)
333 TPosixRequestQueue& queue = iQueues[aQueue];
334 queue.AddLast(aRequest);
335 if (queue.IsFirst(&aRequest))
336 aRequest.StartAsynch(); // queue was empty, so start straight away
339 void CFileDescBase::Remove(CPosixRequest& aRequest, IOQueues aQueue)
341 TPosixRequestQueue& queue = iQueues[aQueue];
342 TBool wasFirst = queue.IsFirst(&aRequest);
343 queue.Remove(aRequest);
346 if (!queue.IsEmpty())
347 queue.First()->StartAsynch(); // start the next outstanding request
352 // Generic (non-virtual) handling for Close
354 TInt CFileDescBase::Close()
365 TInt CFileDescBase::FinalClose()
371 // Simple implementation of File handling
373 static int MapMode(int aMode, TUint& fMode)
375 // EPOC32 doesn't support Write-Only
377 if (aMode & (O_WRONLY|O_RDWR))
380 fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareAny;
385 fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareReadersOnly;
388 fMode |= (aMode & O_TEXT) ? EFileStreamText : EFileStream;
390 return aMode & (O_CREAT|O_TRUNC|O_APPEND|O_EXCL);
393 CFileDesc::CFileDesc()
394 :CFileDescBase(), iSize(EBufferSize), iExt(-1)
397 CFileDesc::~CFileDesc()
403 TInt CFileDesc::FinalClose()
408 TInt CFileDesc::Open(RFs& aSession, const TDesC& aName, int mode, int /*perms*/)
413 iDrive=(TInt16)TDriveUnit(aName);
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
419 int mapped=MapMode(mode, fMode);
423 err = iFile.Create(aSession, aName, fMode);
425 case O_CREAT|O_TRUNC:
426 err = iFile.Replace(aSession, aName, fMode);
429 err = iFile.Open(aSession, aName, fMode);
430 if (err == KErrPathNotFound)
432 // missing directories etc, so fail directly
437 err = iFile.Replace(aSession, aName, fMode);
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
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))
455 if ((mode & O_BUFFERED) == 0)
460 TInt CFileDesc::LSeek (int& offset, int whence)
500 TInt lag = iPos - pos;
501 if (lag >= 0 && lag <= (iEnd - iBuffer))
523 void CFileDesc::MapStat(struct stat& st, const TTime& aModTime, TUint& aAttr)
525 st.st_mode = (aAttr&KEntryAttDir) ? S_IFDIR:S_IFREG;
526 if ((aAttr&KEntryAttReadOnly)==0)
527 st.st_mode |= S_IWUSR;
529 st.st_mtime = as_time_t(aModTime);
533 TInt CFileDesc::FStat (struct stat* st)
539 err = iFile.Att(att);
542 err = iFile.Modified(modtime);
549 st->st_dev = st->st_rdev = iDrive;
550 MapStat(*st, modtime, att);
558 TInt CFileDesc::Alloc()
562 iBuffer = new TUint8[iSize];
569 TInt CFileDesc::FileRead(TUint8* aPtr,TInt aLength)
571 TPtr8 ptr(aPtr,aLength);
572 TInt r=iFile.Read(iPos,ptr);
583 TInt CFileDesc::FileWrite(TUint8* aPtr,TInt aLength)
585 TPtrC8 ptr(aPtr,aLength);
586 TInt r = iFile.Write(iPos,ptr);
590 if (iPos > iExt && iExt >= 0)
596 TInt CFileDesc::Flush()
600 TInt r = FileWrite(iBuffer, iPtr-iBuffer);
608 TInt CFileDesc::DoRead (TDes8& aDesc)
610 if (iState != EReading)
612 TInt ret = (iState == EAlloc) ? Alloc() : Flush();
616 iPtr = iEnd = iBuffer;
619 TUint8* p = (TUint8*) aDesc.Ptr();
620 TInt max = aDesc.MaxLength();
621 TInt avail = iEnd - iPtr;
622 TInt len = Min(max, avail);
625 p = Mem::Copy(p, iPtr, len);
631 TInt ret = FileRead(p, max);
638 TInt ret = FileRead(iBuffer, Min(max + EReadAhead, iSize));
642 p = Mem::Copy(p, iBuffer, len);
643 iPtr = iBuffer + len;
644 iEnd = iBuffer + ret;
646 aDesc.SetLength(p-aDesc.Ptr());
650 void CFileDesc::Read (TDes8& aDesc, TRequestStatus& aStatus)
652 Complete(aStatus,DoRead(aDesc));
655 TInt CFileDesc::DoWrite (TDes8& aDesc)
657 if (iState != EWriting)
659 if (iState == EAlloc)
670 iEnd = iBuffer + iSize;
673 TUint8* p = (TUint8*) aDesc.Ptr();
674 TInt max = aDesc.Length();
675 TInt avail = iEnd - iPtr;
676 TInt len = Min(max, avail);
679 iPtr = Mem::Copy(iPtr, p, len);
689 return FileWrite(p, max);
690 iPtr = Mem::Copy(iPtr, p, max);
694 void CFileDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
696 Complete(aStatus,DoWrite(aDesc));
699 TInt CFileDesc::DoSync()
701 if (iState == EWriting)
707 return iFile.Flush();
710 void CFileDesc::Sync(TRequestStatus& aStatus)
712 Complete(aStatus,DoSync());
715 TInt CFileDesc::Pos()
718 if (iState == EReading)
719 pos -= (iEnd - iPtr);
720 else if (iState == EWriting)
721 pos += (iPtr - iBuffer);
725 TInt CFileDesc::Ext()
729 TInt r = iFile.Size(iExt);
733 return Max(iExt, Pos());
736 TInt CFileDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
741 // some useful sums about the current state of the file
746 int *param=REINTERPRET_CAST(int*,aParam);
751 *param=(size-curoff);
755 int mask=E32SELECT_WRITE;
757 mask |= E32SELECT_READ;
758 *param=(*param)&mask; // but don't block
762 ret=KErrNotSupported;
768 // Extra support for temporary files
770 TInt CTempFileDesc::Open(RFs& aSession, const TDesC& aPath)
773 iDrive=(TInt16)TDriveUnit(aPath);
774 TInt err=iFile.Temp(aSession, aPath, iName, EFileShareAny);
778 TInt CTempFileDesc::FinalClose()
781 TInt err=iSession.Delete(iName);