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.
14 // Implementation of pipes
19 #include <sys/errno.h>
22 // Child end of the pipe
24 CPipeChildDesc::CPipeChildDesc(TInt anIndex, RPosixSession& aSession)
25 : CFileDescBase(), iIndex(anIndex), iSession(aSession), iParamDes(0,0,0)
28 TInt CPipeChildDesc::LSeek (int&, int)
30 return ESPIPE; // can't seek on a pipe
33 TInt CPipeChildDesc::FStat(struct stat *st)
35 // I am a fifo about which little is known
36 st->st_mode = S_IFIFO;
41 void CPipeChildDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
43 if (iClientClosed || !IsReadable())
45 Complete(aStatus,KErrEof);
48 TIpcArgs args(iIndex,&aBuf,aBuf.MaxLength());
49 iSession.Request(PMPipeRead,args,aStatus); // asynchronous request
52 void CPipeChildDesc::ReadCancel()
57 TInt CPipeChildDesc::ReadCompletion(TDes8& aDesc, TInt aStatus)
62 aDesc.Zero(); // set read length to zero
63 return KErrNone; // indicates graceful close at the other end
68 void CPipeChildDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
70 if (iClientClosed || !IsWriteable())
72 Complete(aStatus,KErrEof);
75 TIpcArgs args(iIndex,&aDesc,aDesc.Length());
76 iSession.Request(PMPipeWrite,args,aStatus); // asynchronous request
79 void CPipeChildDesc::WriteCancel()
84 TInt CPipeChildDesc::WriteCompletion(TDes8& /*aDesc*/, TInt aStatus)
91 void CPipeChildDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
93 // The work of the Ioctl is done in the parent, including writing back to aParam?
94 // Use the default completion which just returns aStatus.Int()
99 Complete(aStatus,KErrEof);
102 iParamDes.Set((TText8*)aParam,4,4);
103 TIpcArgs args(iIndex,aCmd,&iParamDes);
104 if (aCmd==E32IOSELECT)
105 args.Set(3, *((TInt*)aParam));
106 iSession.Request(PMPipeIoctl,args,aStatus); // asynchronous request
109 void CPipeChildDesc::IoctlCancel()
114 void CPipeChildDesc::Cancel(TInt aType)
118 TIpcArgs args(iIndex,aType);
119 iSession.Request(PMPipeCancel,args);
122 TInt CPipeChildDesc::FinalClose()
125 TIpcArgs args(iIndex);
126 return iSession.Request(PMPipeClose,args); // synchronous request
130 // Parent end of the pipe, where the real work is done
133 CPipeDesc::CPipeDesc(TInt anIndex) : CFileDescBase()
138 void CPipeDesc::SetClientSide(CPipeDesc*& aClientPointer)
140 iClientSide=&aClientPointer;
143 _LIT(KCPipeDescPanic, "CPipeDesc");
144 void CPipeDesc::Panic(TInt aReason)
146 User::Panic(KCPipeDescPanic,aReason);
149 void CPipeDesc::Panic(RMessage2& aMessage, TInt aReason)
151 aMessage.Panic(KCPipeDescPanic,aReason);
154 TInt CPipeDesc::LSeek (int&, int)
156 return ESPIPE; // can't seek on a pipe
159 TInt CPipeDesc::FStat(struct stat *st)
161 // I am a fifo about which little is known
162 st->st_mode = S_IFIFO;
167 void CPipeDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
171 Complete(aStatus, KErrEof); // avoids treading on iStatus of pending Write
174 __ASSERT_DEBUG(iStatus==0,Panic(1));
178 User::RequestComplete(iStatus,KErrEof);
182 if (ClientIoctlPending())
183 CompleteClientIoctl();
184 if (iClientLength!=0)
185 TransferFromClient();
188 void CPipeDesc::ReadCancel()
193 TInt CPipeDesc::ReadCompletion(TDes8& aDesc, TInt aStatus)
195 if (aStatus==KErrEof)
198 aDesc.Zero(); // set read length to zero
199 return KErrNone; // indicates graceful close at the other end
204 void CPipeDesc::Write(TDes8& aDesc, TRequestStatus& aStatus)
208 Complete(aStatus, KErrEof); // avoids treading on iStatus of pending Read
211 __ASSERT_DEBUG(iStatus==0,Panic(2));
215 User::RequestComplete(iStatus,KErrEof);
218 iWriteBuf.Set(aDesc);
219 if (ClientIoctlPending())
220 CompleteClientIoctl();
221 if (iClientLength!=0)
225 void CPipeDesc::WriteCancel()
230 TInt CPipeDesc::WriteCompletion(TDes8& /*aDesc*/, TInt aStatus)
232 if (aStatus==KErrEof)
237 void CPipeDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
240 iIoctlStatus=&aStatus;
241 int *param=REINTERPRET_CAST(int*,aParam);
245 // synchronous ioctls are handled in the completion routine.
249 int mask=(*param)&SelectMask();
250 if (mask!=0 && iClientLength==0)
251 return; // wait for client to show up
255 ret=KErrNotSupported;
258 User::RequestComplete(iIoctlStatus,ret);
261 TInt CPipeDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus)
266 int *param=REINTERPRET_CAST(int*,aParam);
271 *param=iClientLength; // 0 if no outstanding client data
273 *param=0; // claim that no data is available
278 if (iClientLength!=0)
280 *param=(*param)&mask;
284 ret=KErrNotSupported;
290 void CPipeDesc::IoctlCancel()
292 User::RequestComplete(iIoctlStatus,KErrCancel);
295 void CPipeDesc::Cancel()
297 // Pipes are unidirectional, so don't need to distinguish between
298 // ReadCancel and WriteCancel
299 User::RequestComplete(iStatus,KErrCancel);
302 // Client-side interface
304 void CPipeDesc::ClientWrite(const RMessage2& aMessage)
306 __ASSERT_DEBUG(iClientLength==0,Panic(3));
309 aMessage.Complete(KErrEof);
312 iClientLength=aMessage.Int2();
316 User::RequestComplete(iIoctlStatus,KErrNone);
318 TransferFromClient();
321 void CPipeDesc::ClientRead(const RMessage2& aMessage)
323 __ASSERT_DEBUG(iClientLength==0,Panic(4));
326 aMessage.Complete(KErrEof);
329 iClientLength=aMessage.Int2();
332 User::RequestComplete(iIoctlStatus,KErrNone);
337 void CPipeDesc::ClientIoctl(const RMessage2& aMessage)
339 __ASSERT_DEBUG(!ClientIoctlPending(),Panic(7));
342 aMessage.Complete(KErrEof);
345 iClientIoctlPending=1;
346 iIoctlMessage=aMessage;
348 switch (aMessage.Int1())
351 // synchronous ioctls are handled in the completion routine.
355 int mask=aMessage.Int3();
356 mask&=ClientSelectMask();
357 if (mask!=0 && iStatus==0)
358 return; // wait for parent activity
362 ret=KErrNotSupported;
365 CompleteClientIoctl(ret);
368 void CPipeDesc::ClientCancel(const RMessage2& aMessage)
370 if (aMessage.Int1()==PMPipeIoctl)
372 if (ClientIoctlPending())
373 CompleteClientIoctl(KErrCancel);
376 // Pipes are unidirectional, so Read and Write are cancelled by
377 // cancelling the current client operation.
379 if (iClientLength!=0)
381 iMessage.Complete(KErrCancel);
386 void CPipeDesc::ClientClose()
389 // terminate any pending requests
391 User::RequestComplete(iStatus,KErrEof);
392 if (ClientIoctlPending())
393 CompleteClientIoctl(KErrEof);
394 if (iClientLength!=0)
396 iMessage.Complete(KErrEof);
401 TInt CPipeDesc::FinalClose()
412 void CPipeDesc::TransferFromClient()
414 // Handle transfer of data from client to parent.
415 // Always complete the parent read, but only complete the child write when
416 // all of the data has been consumed.
419 TRAPD(err,iMessage.ReadL(1,*iReadBuf,iClientOffset));
424 ClientClose(); // will complete the parent read
427 TInt length=iReadBuf->Length(); // record the amount of data transferred
428 User::RequestComplete(iStatus,KErrNone);
429 iClientOffset+=length;
430 iClientLength-=length;
431 if (iClientLength==0)
432 iMessage.Complete(KErrNone);
435 void CPipeDesc::TransferToClient()
437 // Handle transfer from parent to client
438 // Always complete the client read, but only complete the parent write when
439 // all of the data has been consumed.
443 TInt length=iWriteBuf.Length();
445 if (iClientLength >= length)
447 TRAP(err,iMessage.WriteL(1,iWriteBuf,0));
451 written=iClientLength;
452 TRAP(err,iMessage.WriteL(1,iWriteBuf.Left(written),0));
458 ClientClose(); // will complete the parent write
461 iMessage.Complete(KErrNone);
464 User::RequestComplete(iStatus,KErrNone);
466 iWriteBuf.Set(iWriteBuf.Right(length));
469 void CPipeDesc::CompleteClientIoctl(TInt ret)
473 iIoctlMessage.Complete(ret);
474 iClientIoctlPending=0;
477 CompleteClientIoctl();
480 void CPipeDesc::CompleteClientIoctl()
482 // Complete outstanding PMPipeIoctl message
487 switch (iIoctlMessage.Int1())
490 if (IsWriteable() && iStatus!=0)
491 param=iWriteBuf.Length();
493 param=0; // claim that no data is available
499 mask=ClientSelectMask();
500 param=(iIoctlMessage.Int3())&mask;
504 ret=KErrNotSupported;
509 TPtrC8 paramReturn((const TText8*)¶m,4);
510 TRAP(ret,iIoctlMessage.WriteL(2,paramReturn,0));
512 iIoctlMessage.Complete(ret);
513 iClientIoctlPending=0;