1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/USTLIB/FTABLE.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,400 @@
1.4 +// Copyright (c) 1999-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 +// Handle a table of CFileDescBase pointers
1.18 +//
1.19 +//
1.20 +
1.21 +#include "SYSIF.H"
1.22 +#include "FDESC.H"
1.23 +#include "LTIME.H"
1.24 +#include "LPOSIX.H"
1.25 +#include <fcntl.h>
1.26 +#include <sys/errno.h>
1.27 +
1.28 +#define RESERVED(i) ((CFileDescBase*)((i)+1))
1.29 +
1.30 +const TInt MINFILES = 8;
1.31 +
1.32 +CFileTable::CFileTable() : iFids(MINFILES)
1.33 + {
1.34 + }
1.35 +
1.36 +void CFileTable::InitL()
1.37 + {
1.38 + CFileDescBase* ptr=0;
1.39 + iFids.InsertL(0, ptr, 8); // set up the first 8 entries with zero
1.40 + }
1.41 +
1.42 +CFileTable::~CFileTable()
1.43 + {
1.44 + Close();
1.45 + }
1.46 +
1.47 +void CFileTable::Close()
1.48 + {
1.49 + for (TInt aFid=0; aFid<iFids.Count(); aFid++)
1.50 + {
1.51 + if (iFids[aFid]!=0 && iFids[aFid]!=RESERVED(aFid))
1.52 + {
1.53 + iFids[aFid]->RecvFromCancel();
1.54 + iFids[aFid]->Close();
1.55 + }
1.56 + Release(aFid);
1.57 + }
1.58 + }
1.59 +
1.60 +void CFileTable::Release(TInt aFid)
1.61 + {
1.62 + iFids[aFid]=0;
1.63 + if (aFid<MINFILES || aFid<iFids.Count()-1)
1.64 + return;
1.65 + // opportunity to shrink the array
1.66 + while (aFid>=MINFILES && iFids[aFid]==0)
1.67 + {
1.68 + iFids.Delete(aFid);
1.69 + aFid--;
1.70 + }
1.71 + iFids.Compress();
1.72 + }
1.73 +
1.74 +void CFileTable::Default(CFileDescBase* aConsole)
1.75 + {
1.76 + if (iFids[0]==0)
1.77 + iFids[0]=aConsole->Dup();
1.78 + if (iFids[1]==0)
1.79 + iFids[1]=aConsole->Dup();
1.80 + if (iFids[2]==0)
1.81 + iFids[2]=aConsole->Dup();
1.82 + }
1.83 +
1.84 +TInt CFileTable::Attach(TInt aFid, CFileDescBase* aFile)
1.85 + {
1.86 + if (aFid<0 || aFid>=iFids.Count() || (iFids[aFid] != 0 && iFids[aFid]!=RESERVED(aFid)))
1.87 + return KErrArgument;
1.88 + iFids[aFid]=aFile;
1.89 + return KErrNone;
1.90 + }
1.91 +
1.92 +TInt CFileTable::Reserve()
1.93 + {
1.94 + TInt aFid=0;
1.95 + TInt err=KErrNone;
1.96 + for (aFid=0; aFid<iFids.Count(); aFid++)
1.97 + if (iFids[aFid]==0)
1.98 + goto success;
1.99 + TRAP(err,iFids.ExtendL());
1.100 + if (err!=KErrNone)
1.101 + return err;
1.102 + aFid=iFids.Count()-1;
1.103 +
1.104 +success:
1.105 + iFids[aFid]=RESERVED(aFid);
1.106 + return aFid;
1.107 + }
1.108 +
1.109 +TInt CFileTable::Reserve(int aFids[3])
1.110 + {
1.111 + TInt i=0;
1.112 + for (i=0; i<3; i++)
1.113 + {
1.114 + if (aFids[i]==-1)
1.115 + {
1.116 + TInt fd=Reserve();
1.117 + if (fd<0)
1.118 + {
1.119 + Detach(aFids); // release the ones we did get
1.120 + return KErrInUse;
1.121 + }
1.122 + aFids[i]=fd;
1.123 + }
1.124 + }
1.125 + return KErrNone;
1.126 + }
1.127 +
1.128 +TInt CFileTable::Detach(int aFids[3])
1.129 + {
1.130 + TInt i=0;
1.131 + for (i=0; i<3; i++)
1.132 + {
1.133 + if (aFids[i]>=0)
1.134 + Attach(aFids[i],0);
1.135 + }
1.136 + return KErrInUse;
1.137 + }
1.138 +
1.139 +TInt CFileTable::Detach(TInt aFid, CFileDescBase*& aDetached)
1.140 + {
1.141 + if (aFid<0 || aFid>=iFids.Count())
1.142 + return KErrArgument;
1.143 + aDetached=iFids[aFid];
1.144 + Release(aFid);
1.145 + return KErrNone;
1.146 + }
1.147 +
1.148 +TInt CFileTable::At(TInt aFid, CFileDescBase*& aFound) const
1.149 + {
1.150 + if (aFid<0 || aFid>=iFids.Count())
1.151 + return KErrArgument;
1.152 + aFound=iFids[aFid];
1.153 + if (aFound==0)
1.154 + return KErrNotFound;
1.155 + return KErrNone;
1.156 + }
1.157 +
1.158 +TInt CFileTable::Dup(TInt& aFid)
1.159 + {
1.160 + if (aFid<0 || aFid>=iFids.Count())
1.161 + return KErrArgument;
1.162 + CFileDescBase* fdesc=iFids[aFid];
1.163 + if (fdesc==0)
1.164 + return KErrNotFound;
1.165 + TInt aFid2=0;
1.166 + for (aFid2=0; aFid2<iFids.Count(); aFid2++)
1.167 + if (iFids[aFid2]==0)
1.168 + {
1.169 + iFids[aFid2]=fdesc->Dup();
1.170 + aFid=aFid2;
1.171 + return KErrNone;
1.172 + }
1.173 + return KErrInUse;
1.174 + }
1.175 +
1.176 +TInt CFileTable::Dup2(TInt aFid, TInt aFid2)
1.177 + {
1.178 + if (aFid<0 || aFid>=iFids.Count() || aFid2<0 || aFid2>=iFids.Count() || aFid==aFid2)
1.179 + return KErrArgument;
1.180 + CFileDescBase* fdesc=iFids[aFid];
1.181 + if (fdesc==0)
1.182 + return KErrNotFound;
1.183 + CFileDescBase* old=iFids[aFid2];
1.184 + iFids[aFid2]=fdesc->Dup();
1.185 + if (old)
1.186 + old->Close();
1.187 + return KErrNone;
1.188 + }
1.189 +
1.190 +// Simple synchronous services
1.191 +
1.192 +int CFileTable::dup (int fid, int& anErrno)
1.193 + {
1.194 + TInt ret=Dup(fid);
1.195 + if (ret==KErrNone)
1.196 + return fid;
1.197 + return MapError(ret,anErrno);
1.198 + }
1.199 +
1.200 +int CFileTable::dup2 (int fid, int fid2, int& anErrno)
1.201 + {
1.202 + TInt err=Dup2(fid,fid2);
1.203 + return MapError(err,anErrno);
1.204 + }
1.205 +
1.206 +//int CFileTable::open (const char* name, int mode, int perms, int& anErrno, RFs& aFs)
1.207 +//int CFileTable::open (const wchar_t* name, int mode, int perms, int& anErrno, RFs& aFs)
1.208 +int CFileTable::open (const wchar_t* name, int mode, int perms, int& anErrno, RSessionBase& aFs)
1.209 + {
1.210 + int fd=Reserve();
1.211 + TInt err=fd;
1.212 + if (fd>=0)
1.213 + {
1.214 + //coverity[alloc_fn]
1.215 + //coverity[var_assign]
1.216 + CFileDescBase *f=CFileDescBase::Open(aFs,name,mode,perms,err);
1.217 + if (!err)
1.218 + {
1.219 + err=Attach(fd,f);
1.220 + if (!err)
1.221 + return fd;
1.222 + delete f;
1.223 + }
1.224 + Attach(fd,0); // cancel the reservation
1.225 + //coverity[leaked_storage]
1.226 + }
1.227 + return MapError(err,anErrno);
1.228 + }
1.229 +
1.230 +int CFileTable::socket (int family, int style, int protocol, int& anErrno, RSocketServ& aSs)
1.231 + {
1.232 + int fd=Reserve();
1.233 + TInt err=fd;
1.234 + if (fd>=0)
1.235 + {
1.236 + CFileDescBase *f=CFileDescBase::Socket(aSs,family,style,protocol,err);
1.237 + if (!err)
1.238 + {
1.239 + CleanupStack::PushL(f);
1.240 + err=Attach(fd,f);
1.241 + CleanupStack::PopAndDestroy(f);
1.242 +
1.243 + if (!err)
1.244 + {
1.245 + return fd;
1.246 + }
1.247 +
1.248 + }
1.249 +
1.250 + Attach(fd,0); // cancel the reservation
1.251 + }
1.252 +
1.253 + return MapError(err,anErrno);
1.254 + }
1.255 +
1.256 +int CFileTable::userclose(int fid, int& anErrno)
1.257 + {
1.258 + CFileDescBase *f=0;
1.259 + TInt err=At(fid,f);
1.260 + if (!err)
1.261 + {
1.262 + f->UserClose();
1.263 + close(fid, anErrno);
1.264 + }
1.265 + else
1.266 + {
1.267 + if (KErrNotFound == err)
1.268 + err = EBADF;
1.269 + }
1.270 + return MapError(err,anErrno);
1.271 + }
1.272 +
1.273 +int CFileTable::close (int fid, int& anErrno)
1.274 + {
1.275 + CFileDescBase *f=0;
1.276 + TInt err=Detach(fid,f);
1.277 + if (!err)
1.278 + {
1.279 + if (f==0)
1.280 + {
1.281 + err=EBADF;
1.282 + }
1.283 + else
1.284 + {
1.285 + f->RecvFromCancel();
1.286 + err=f->Close();
1.287 + }
1.288 + }
1.289 + return MapError(err,anErrno);
1.290 + }
1.291 +
1.292 +
1.293 +
1.294 +int CFileTable::lseek (int fid, int offset, int whence, int& anErrno)
1.295 + {
1.296 + CFileDescBase *f=0;
1.297 + TInt err=At(fid,f);
1.298 + if (!err)
1.299 + {
1.300 + err=f->LSeek(offset, whence);
1.301 + if (err==KErrNone)
1.302 + return offset;
1.303 + }
1.304 + return MapError(err,anErrno);
1.305 + }
1.306 +
1.307 +int CFileTable::fstat (int fid, struct stat *st, int& anErrno)
1.308 + {
1.309 + CFileDescBase *f=0;
1.310 + TInt err=At(fid,f);
1.311 + if (!err)
1.312 + err=f->FStat(st);
1.313 + return MapError(err,anErrno);
1.314 + }
1.315 +
1.316 +int CFileTable::listen (int fid, int n, int& anErrno)
1.317 + {
1.318 + CFileDescBase *f=0;
1.319 + TInt err=At(fid,f);
1.320 + if (!err)
1.321 + err=f->Listen(n);
1.322 + return MapError(err,anErrno);
1.323 + }
1.324 +
1.325 +int CFileTable::bind (int fid, TSockAddr& address, int& anErrno)
1.326 + {
1.327 + CFileDescBase *f=0;
1.328 + TInt err=At(fid,f);
1.329 + if (!err)
1.330 + err=f->Bind(address);
1.331 + return MapError(err,anErrno);
1.332 + }
1.333 +
1.334 +int CFileTable::sockname (int fid, TSockAddr& address, int anEnd, int& anErrno)
1.335 + {
1.336 + CFileDescBase *f=0;
1.337 + TInt err=At(fid,f);
1.338 + if (!err)
1.339 + err=f->SockName(anEnd, address);
1.340 + return MapError(err,anErrno);
1.341 + }
1.342 +
1.343 +int CFileTable::getsockopt (int fid, int level, int opt, void* buf, unsigned long* len, int& anErrno)
1.344 + {
1.345 + CFileDescBase *f=0;
1.346 + TInt err=At(fid,f);
1.347 + if (!err)
1.348 + {
1.349 + TPtr8 ptr((TText8 *)buf, *len, *len);
1.350 + err=f->GetSockOpt(opt,level,ptr);
1.351 + if (err==0)
1.352 + *len=ptr.Length();
1.353 + }
1.354 + return MapError(err,anErrno);
1.355 + }
1.356 +
1.357 +int CFileTable::setsockopt (int fid, int level, int opt, void* buf, unsigned long len, int& anErrno)
1.358 + {
1.359 + CFileDescBase *f=0;
1.360 + TInt err=At(fid,f);
1.361 + if (err==KErrNone)
1.362 + {
1.363 + //Negative option is not supported and have not been implemented yet
1.364 + //anErrno is then mapped to ENOSYS(88) (function not implemented yet)
1.365 + if (opt<=0)
1.366 + return MapError(KErrNotSupported,anErrno);
1.367 + TPtrC8 ptr((TText8 *)buf, len);
1.368 + err=f->SetSockOpt(opt,level,ptr);
1.369 + }
1.370 + return MapError(err,anErrno);
1.371 + }
1.372 +
1.373 +int CFileTable::ioctlcomplete (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno)
1.374 + {
1.375 + CFileDescBase *f=0;
1.376 + TInt err=At(fid,f);
1.377 + if (!err)
1.378 + err=f->IoctlCompletion(cmd,param, aStatus.Int());
1.379 + return MapError(err,anErrno);
1.380 + }
1.381 +
1.382 +int CFileTable::ioctlcancel (int fid, int& anErrno)
1.383 + {
1.384 + CFileDescBase *f=0;
1.385 + TInt err=At(fid,f);
1.386 + if (!err)
1.387 + f->IoctlCancel();
1.388 + return MapError(err,anErrno);
1.389 + }
1.390 +
1.391 +// Preparation for an Asynchronous service
1.392 +//
1.393 +// The CFileDescBase* should be Closed after completion: the use of Dup prevents other
1.394 +// clients from invalidating the pointer during an asynchronous operation.
1.395 +
1.396 +TInt CFileTable::Asynch (int fid, CFileDescBase*& aFile)
1.397 + {
1.398 + TInt err=At(fid,aFile);
1.399 + if (!err)
1.400 + aFile->Dup();
1.401 + return err;
1.402 + }
1.403 +