sl@0: // Copyright (c) 1999-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: // Handle a table of CFileDescBase pointers sl@0: // sl@0: // sl@0: sl@0: #include "SYSIF.H" sl@0: #include "FDESC.H" sl@0: #include "LTIME.H" sl@0: #include "LPOSIX.H" sl@0: #include sl@0: #include sl@0: sl@0: #define RESERVED(i) ((CFileDescBase*)((i)+1)) sl@0: sl@0: const TInt MINFILES = 8; sl@0: sl@0: CFileTable::CFileTable() : iFids(MINFILES) sl@0: { sl@0: } sl@0: sl@0: void CFileTable::InitL() sl@0: { sl@0: CFileDescBase* ptr=0; sl@0: iFids.InsertL(0, ptr, 8); // set up the first 8 entries with zero sl@0: } sl@0: sl@0: CFileTable::~CFileTable() sl@0: { sl@0: Close(); sl@0: } sl@0: sl@0: void CFileTable::Close() sl@0: { sl@0: for (TInt aFid=0; aFidRecvFromCancel(); sl@0: iFids[aFid]->Close(); sl@0: } sl@0: Release(aFid); sl@0: } sl@0: } sl@0: sl@0: void CFileTable::Release(TInt aFid) sl@0: { sl@0: iFids[aFid]=0; sl@0: if (aFid=MINFILES && iFids[aFid]==0) sl@0: { sl@0: iFids.Delete(aFid); sl@0: aFid--; sl@0: } sl@0: iFids.Compress(); sl@0: } sl@0: sl@0: void CFileTable::Default(CFileDescBase* aConsole) sl@0: { sl@0: if (iFids[0]==0) sl@0: iFids[0]=aConsole->Dup(); sl@0: if (iFids[1]==0) sl@0: iFids[1]=aConsole->Dup(); sl@0: if (iFids[2]==0) sl@0: iFids[2]=aConsole->Dup(); sl@0: } sl@0: sl@0: TInt CFileTable::Attach(TInt aFid, CFileDescBase* aFile) sl@0: { sl@0: if (aFid<0 || aFid>=iFids.Count() || (iFids[aFid] != 0 && iFids[aFid]!=RESERVED(aFid))) sl@0: return KErrArgument; sl@0: iFids[aFid]=aFile; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CFileTable::Reserve() sl@0: { sl@0: TInt aFid=0; sl@0: TInt err=KErrNone; sl@0: for (aFid=0; aFid=0) sl@0: Attach(aFids[i],0); sl@0: } sl@0: return KErrInUse; sl@0: } sl@0: sl@0: TInt CFileTable::Detach(TInt aFid, CFileDescBase*& aDetached) sl@0: { sl@0: if (aFid<0 || aFid>=iFids.Count()) sl@0: return KErrArgument; sl@0: aDetached=iFids[aFid]; sl@0: Release(aFid); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CFileTable::At(TInt aFid, CFileDescBase*& aFound) const sl@0: { sl@0: if (aFid<0 || aFid>=iFids.Count()) sl@0: return KErrArgument; sl@0: aFound=iFids[aFid]; sl@0: if (aFound==0) sl@0: return KErrNotFound; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CFileTable::Dup(TInt& aFid) sl@0: { sl@0: if (aFid<0 || aFid>=iFids.Count()) sl@0: return KErrArgument; sl@0: CFileDescBase* fdesc=iFids[aFid]; sl@0: if (fdesc==0) sl@0: return KErrNotFound; sl@0: TInt aFid2=0; sl@0: for (aFid2=0; aFid2Dup(); sl@0: aFid=aFid2; sl@0: return KErrNone; sl@0: } sl@0: return KErrInUse; sl@0: } sl@0: sl@0: TInt CFileTable::Dup2(TInt aFid, TInt aFid2) sl@0: { sl@0: if (aFid<0 || aFid>=iFids.Count() || aFid2<0 || aFid2>=iFids.Count() || aFid==aFid2) sl@0: return KErrArgument; sl@0: CFileDescBase* fdesc=iFids[aFid]; sl@0: if (fdesc==0) sl@0: return KErrNotFound; sl@0: CFileDescBase* old=iFids[aFid2]; sl@0: iFids[aFid2]=fdesc->Dup(); sl@0: if (old) sl@0: old->Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: // Simple synchronous services sl@0: sl@0: int CFileTable::dup (int fid, int& anErrno) sl@0: { sl@0: TInt ret=Dup(fid); sl@0: if (ret==KErrNone) sl@0: return fid; sl@0: return MapError(ret,anErrno); sl@0: } sl@0: sl@0: int CFileTable::dup2 (int fid, int fid2, int& anErrno) sl@0: { sl@0: TInt err=Dup2(fid,fid2); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: //int CFileTable::open (const char* name, int mode, int perms, int& anErrno, RFs& aFs) sl@0: //int CFileTable::open (const wchar_t* name, int mode, int perms, int& anErrno, RFs& aFs) sl@0: int CFileTable::open (const wchar_t* name, int mode, int perms, int& anErrno, RSessionBase& aFs) sl@0: { sl@0: int fd=Reserve(); sl@0: TInt err=fd; sl@0: if (fd>=0) sl@0: { sl@0: //coverity[alloc_fn] sl@0: //coverity[var_assign] sl@0: CFileDescBase *f=CFileDescBase::Open(aFs,name,mode,perms,err); sl@0: if (!err) sl@0: { sl@0: err=Attach(fd,f); sl@0: if (!err) sl@0: return fd; sl@0: delete f; sl@0: } sl@0: Attach(fd,0); // cancel the reservation sl@0: //coverity[leaked_storage] sl@0: } sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::socket (int family, int style, int protocol, int& anErrno, RSocketServ& aSs) sl@0: { sl@0: int fd=Reserve(); sl@0: TInt err=fd; sl@0: if (fd>=0) sl@0: { sl@0: CFileDescBase *f=CFileDescBase::Socket(aSs,family,style,protocol,err); sl@0: if (!err) sl@0: { sl@0: CleanupStack::PushL(f); sl@0: err=Attach(fd,f); sl@0: CleanupStack::PopAndDestroy(f); sl@0: sl@0: if (!err) sl@0: { sl@0: return fd; sl@0: } sl@0: sl@0: } sl@0: sl@0: Attach(fd,0); // cancel the reservation sl@0: } sl@0: sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::userclose(int fid, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: { sl@0: f->UserClose(); sl@0: close(fid, anErrno); sl@0: } sl@0: else sl@0: { sl@0: if (KErrNotFound == err) sl@0: err = EBADF; sl@0: } sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::close (int fid, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=Detach(fid,f); sl@0: if (!err) sl@0: { sl@0: if (f==0) sl@0: { sl@0: err=EBADF; sl@0: } sl@0: else sl@0: { sl@0: f->RecvFromCancel(); sl@0: err=f->Close(); sl@0: } sl@0: } sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: sl@0: sl@0: int CFileTable::lseek (int fid, int offset, int whence, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: { sl@0: err=f->LSeek(offset, whence); sl@0: if (err==KErrNone) sl@0: return offset; sl@0: } sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::fstat (int fid, struct stat *st, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: err=f->FStat(st); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::listen (int fid, int n, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: err=f->Listen(n); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::bind (int fid, TSockAddr& address, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: err=f->Bind(address); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::sockname (int fid, TSockAddr& address, int anEnd, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: err=f->SockName(anEnd, address); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::getsockopt (int fid, int level, int opt, void* buf, unsigned long* len, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: { sl@0: TPtr8 ptr((TText8 *)buf, *len, *len); sl@0: err=f->GetSockOpt(opt,level,ptr); sl@0: if (err==0) sl@0: *len=ptr.Length(); sl@0: } sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::setsockopt (int fid, int level, int opt, void* buf, unsigned long len, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (err==KErrNone) sl@0: { sl@0: //Negative option is not supported and have not been implemented yet sl@0: //anErrno is then mapped to ENOSYS(88) (function not implemented yet) sl@0: if (opt<=0) sl@0: return MapError(KErrNotSupported,anErrno); sl@0: TPtrC8 ptr((TText8 *)buf, len); sl@0: err=f->SetSockOpt(opt,level,ptr); sl@0: } sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::ioctlcomplete (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: err=f->IoctlCompletion(cmd,param, aStatus.Int()); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: int CFileTable::ioctlcancel (int fid, int& anErrno) sl@0: { sl@0: CFileDescBase *f=0; sl@0: TInt err=At(fid,f); sl@0: if (!err) sl@0: f->IoctlCancel(); sl@0: return MapError(err,anErrno); sl@0: } sl@0: sl@0: // Preparation for an Asynchronous service sl@0: // sl@0: // The CFileDescBase* should be Closed after completion: the use of Dup prevents other sl@0: // clients from invalidating the pointer during an asynchronous operation. sl@0: sl@0: TInt CFileTable::Asynch (int fid, CFileDescBase*& aFile) sl@0: { sl@0: TInt err=At(fid,aFile); sl@0: if (!err) sl@0: aFile->Dup(); sl@0: return err; sl@0: } sl@0: