genericopenlibs/cstdlib/USTLIB/FTABLE.CPP
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/cstdlib/USTLIB/FTABLE.CPP	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,400 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Handle a table of CFileDescBase pointers
+// 
+//
+
+#include "SYSIF.H"
+#include "FDESC.H"
+#include "LTIME.H"
+#include "LPOSIX.H"
+#include <fcntl.h>
+#include <sys/errno.h>
+
+#define RESERVED(i)	((CFileDescBase*)((i)+1))
+
+const TInt MINFILES = 8;
+
+CFileTable::CFileTable() : iFids(MINFILES)
+	{
+	}
+
+void CFileTable::InitL()
+	{
+	CFileDescBase* ptr=0;
+	iFids.InsertL(0, ptr, 8);	// set up the first 8 entries with zero
+	}
+
+CFileTable::~CFileTable()
+	{
+	Close();
+	}
+
+void CFileTable::Close()
+	{
+	for (TInt aFid=0; aFid<iFids.Count(); aFid++)
+		{
+		if (iFids[aFid]!=0 && iFids[aFid]!=RESERVED(aFid))
+			{
+			iFids[aFid]->RecvFromCancel();
+			iFids[aFid]->Close();
+			}
+		Release(aFid);
+		}
+	}
+
+void CFileTable::Release(TInt aFid)
+	{
+	iFids[aFid]=0;
+	if (aFid<MINFILES || aFid<iFids.Count()-1)
+		return;
+	// opportunity to shrink the array
+	while (aFid>=MINFILES && iFids[aFid]==0)
+		{
+		iFids.Delete(aFid);
+		aFid--;
+		}
+	iFids.Compress();
+	}
+
+void CFileTable::Default(CFileDescBase* aConsole)
+	{
+	if (iFids[0]==0)
+		iFids[0]=aConsole->Dup();
+	if (iFids[1]==0)
+		iFids[1]=aConsole->Dup();
+	if (iFids[2]==0)
+		iFids[2]=aConsole->Dup();
+	}
+
+TInt CFileTable::Attach(TInt aFid, CFileDescBase* aFile)
+	{
+	if (aFid<0 || aFid>=iFids.Count() || (iFids[aFid] != 0 && iFids[aFid]!=RESERVED(aFid)))
+		return KErrArgument;
+	iFids[aFid]=aFile;
+	return KErrNone;
+	}
+
+TInt CFileTable::Reserve()
+	{
+	TInt aFid=0;
+	TInt err=KErrNone;
+	for (aFid=0; aFid<iFids.Count(); aFid++)
+		if (iFids[aFid]==0)
+			goto success;
+	TRAP(err,iFids.ExtendL());
+	if (err!=KErrNone)
+		return err;
+	aFid=iFids.Count()-1;
+
+success:
+	iFids[aFid]=RESERVED(aFid);
+	return aFid;
+	}
+
+TInt CFileTable::Reserve(int aFids[3])
+	{
+	TInt i=0;
+	for (i=0; i<3; i++)
+		{
+		if (aFids[i]==-1)
+			{
+			TInt fd=Reserve();
+			if (fd<0)
+				{
+				Detach(aFids);	// release the ones we did get
+				return KErrInUse;
+				}
+			aFids[i]=fd;
+			}
+		}
+	return KErrNone;
+	}
+
+TInt CFileTable::Detach(int aFids[3])
+	{
+	TInt i=0;
+	for (i=0; i<3; i++)
+		{
+		if (aFids[i]>=0)
+			Attach(aFids[i],0);
+		}
+	return KErrInUse;
+	}
+
+TInt CFileTable::Detach(TInt aFid, CFileDescBase*& aDetached)
+	{
+	if (aFid<0 || aFid>=iFids.Count())
+		return KErrArgument;
+	aDetached=iFids[aFid];
+	Release(aFid);
+	return KErrNone;
+	}
+
+TInt CFileTable::At(TInt aFid, CFileDescBase*& aFound) const
+	{
+	if (aFid<0 || aFid>=iFids.Count())
+		return KErrArgument;
+	aFound=iFids[aFid];
+	if (aFound==0)
+		return KErrNotFound;
+	return KErrNone;
+	}
+
+TInt CFileTable::Dup(TInt& aFid)
+	{
+	if (aFid<0 || aFid>=iFids.Count())
+		return KErrArgument;
+	CFileDescBase* fdesc=iFids[aFid];
+	if (fdesc==0)
+		return KErrNotFound;
+	TInt aFid2=0;
+	for (aFid2=0; aFid2<iFids.Count(); aFid2++)
+		if (iFids[aFid2]==0)
+			{
+			iFids[aFid2]=fdesc->Dup();
+			aFid=aFid2;
+			return KErrNone;
+			}
+	return KErrInUse;
+	}
+
+TInt CFileTable::Dup2(TInt aFid, TInt aFid2)
+	{
+	if (aFid<0 || aFid>=iFids.Count() || aFid2<0 || aFid2>=iFids.Count() || aFid==aFid2)
+		return KErrArgument;
+	CFileDescBase* fdesc=iFids[aFid];
+	if (fdesc==0)
+		return KErrNotFound;
+	CFileDescBase* old=iFids[aFid2];
+	iFids[aFid2]=fdesc->Dup();
+	if (old)
+		old->Close();
+	return KErrNone;
+	}
+
+// Simple synchronous services
+
+int CFileTable::dup (int fid, int& anErrno)
+	{
+	TInt ret=Dup(fid);
+	if (ret==KErrNone)
+		return fid;
+	return MapError(ret,anErrno);
+	}
+
+int CFileTable::dup2 (int fid, int fid2, int& anErrno)
+	{
+	TInt err=Dup2(fid,fid2);
+	return MapError(err,anErrno);
+	}
+	
+//int CFileTable::open (const char* name, int mode, int perms, int& anErrno, RFs& aFs)
+//int CFileTable::open (const wchar_t* name, int mode, int perms, int& anErrno, RFs& aFs)
+int CFileTable::open (const wchar_t* name, int mode, int perms, int& anErrno, RSessionBase& aFs)
+	{
+	int fd=Reserve();
+	TInt err=fd;
+	if (fd>=0)
+		{
+		//coverity[alloc_fn]
+		//coverity[var_assign]
+		CFileDescBase *f=CFileDescBase::Open(aFs,name,mode,perms,err);
+		if (!err)
+			{
+			err=Attach(fd,f);
+			if (!err)
+				return fd;
+			delete f;
+			}
+		Attach(fd,0);	// cancel the reservation
+		//coverity[leaked_storage]
+		}
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::socket (int family, int style, int protocol, int& anErrno, RSocketServ& aSs)
+	{
+	int fd=Reserve();
+	TInt err=fd;
+	if (fd>=0)
+		{
+		CFileDescBase *f=CFileDescBase::Socket(aSs,family,style,protocol,err);
+		if (!err)
+			{
+			CleanupStack::PushL(f);
+			err=Attach(fd,f);
+			CleanupStack::PopAndDestroy(f);
+			
+			if (!err)
+				{
+				return fd;	
+				}
+			
+			}
+		
+		Attach(fd,0);	// cancel the reservation
+		}
+
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::userclose(int fid, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		{
+		f->UserClose();
+		close(fid, anErrno);
+		}
+	else
+		{
+		if (KErrNotFound == err)
+			err = EBADF;
+		}
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::close (int fid, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=Detach(fid,f);
+	if (!err)
+	   {
+		if (f==0)
+		  {
+			err=EBADF;
+		  }
+		else
+		  {
+		    f->RecvFromCancel();
+			err=f->Close();
+		  }
+	   }
+	return MapError(err,anErrno);
+	}
+
+
+
+int CFileTable::lseek (int fid, int offset, int whence, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		{
+		err=f->LSeek(offset, whence);
+		if (err==KErrNone)
+			return offset;
+		}
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::fstat (int fid, struct stat *st, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		err=f->FStat(st);
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::listen (int fid, int n, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		err=f->Listen(n);
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::bind (int fid, TSockAddr& address, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		err=f->Bind(address);
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::sockname (int fid, TSockAddr& address, int anEnd, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		err=f->SockName(anEnd, address);
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::getsockopt (int fid, int level, int opt, void* buf, unsigned long* len, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		{
+		TPtr8 ptr((TText8 *)buf, *len, *len);
+		err=f->GetSockOpt(opt,level,ptr);
+		if (err==0)
+			*len=ptr.Length();
+		}
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::setsockopt (int fid, int level, int opt, void* buf, unsigned long len, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (err==KErrNone)
+		{
+		//Negative option is not supported and have not been implemented yet
+		//anErrno is then mapped to ENOSYS(88) (function not implemented yet)
+		if (opt<=0)
+			return MapError(KErrNotSupported,anErrno);
+		TPtrC8 ptr((TText8 *)buf, len);
+		err=f->SetSockOpt(opt,level,ptr);
+		}
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::ioctlcomplete (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		err=f->IoctlCompletion(cmd,param, aStatus.Int());
+	return MapError(err,anErrno);
+	}
+
+int CFileTable::ioctlcancel (int fid, int& anErrno)
+	{
+	CFileDescBase *f=0;
+	TInt err=At(fid,f);
+	if (!err)
+		f->IoctlCancel();
+	return MapError(err,anErrno);
+	}
+
+// Preparation for an Asynchronous service
+//
+// The CFileDescBase* should be Closed after completion: the use of Dup prevents other
+// clients from invalidating the pointer during an asynchronous operation.
+
+TInt CFileTable::Asynch (int fid, CFileDescBase*& aFile)
+	{
+	TInt err=At(fid,aFile);
+	if (!err)
+		aFile->Dup();
+	return err;
+	}
+